#include <iostream>
#include <vector>
#include <cstdint>
#include <stdlib.h>
#include <algorithm>
#include <chrono>
#include <cmath>
#include <immintrin.h>
#include <random>
#include <cstring>
#include <thread>
#include <filesystem> //c++17
#include <fstream>
#include "gene.cpp"

const int global_N = 1 << 27; // 512MB   64M*8
//128M double  = 1G size

const int VECTOR_SIZE = 1024;

// #include "xxh3.h"

char ceillog2[256] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};

char ceillog2_compress[128];

union V
{
    // 小端
    struct
    {
        unsigned char h;
        unsigned char g;
        unsigned char f;
        unsigned char e;
        unsigned char d;
        unsigned char c;
        unsigned char b;
        unsigned char a;
    } char8;
    struct
    {
        double a;
    } dou;
    struct
    {
        unsigned long long int a;
    } ull;
    struct
    {
        long long int a;
    } ll;
};

class information
{
    // 8+8+1=17
public:
    // static const unsigned char ceillog2[16] {0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4};
    // unsigned short id;
    unsigned long long int stroageEncounterNum{0};
    unsigned long long int EncounterNum_to_EncodeNum{0};
    // double a0_1 {0};
    unsigned char count_1_sum{0};
    unsigned char ceillog2_1_sum{0};

    void test_print()
    {
        // printf("id=%d,stroageEncounterNum=%x,EncounterNum_to_EncodeNum=%x,count_1_sum=%d\n",id,stroageEncounterNum,EncounterNum_to_EncodeNum,count_1_sum);
    }
};
std::vector<information> information_vec(1 << 16);
void init_information()
{
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 1; i < (1 << 16); i++)
    {
        unsigned long long int stroageEncounterNum = 0;
        unsigned long long int EncounterNum_to_EncodeNum = 0;
        unsigned char c = 0;
        for (unsigned long long int j = 0; j < 16; ++j)
        {
            unsigned long long int tmp = (i >> j) & 1; // 0 or 1
            stroageEncounterNum |= ((j << (4 * c)) * tmp);
            EncounterNum_to_EncodeNum |= (((1ull * c) << (4 * j)));
            c += tmp;
        }
        // information_vec[i-1].id=i-1;
        information_vec[i-1].stroageEncounterNum = stroageEncounterNum;
        information_vec[i-1].EncounterNum_to_EncodeNum = EncounterNum_to_EncodeNum;
        // information_vec[i].a0_1 = 0;
        information_vec[i-1].count_1_sum = c;
        information_vec[i-1].ceillog2_1_sum = ceillog2[c - 1]; // c = 1 -> 16
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
    printf("init duration time = %lf ms\n", duration / 1e6); // 0.706ms

    // for(int i=1;i<=(1<<4);++i){
    //     information_vec[i-1].test_print();
    // }
    // information_vec[65535].test_print();
}
int opt_mod(int a, int b)
{
    // b:[2,255]
    //  if(b==2){
    //      return a&1;
    //  }else{
    //      return a-(a/b)*b;
    //  }
    return a - (a / b) * b; //   a/b效率不高   后续用乘法代替试试效率
}
int opt_div_mod(int a, int b, int c)
{
    // return (a/b)%c
    return opt_mod(a / b, c);
}
int opt_div(int a, int b)
{
    return a / b;
}

template <class T>
int count_one_bit(T num)
{
    // popcnt指令集
    int count = 0;
    while (num)
    {
        num = num & (num - 1);
        count++;
    }
    return count;
}

void find_topk(int num)
{
    num = 1 << num; // 0:1,1:2,2:4,3:8
}
int countLeadingZeros(unsigned char num)
{
    // 如果num为0，则前导0的个数为CHAR_BIT（即8，假设我们使用8位字节）
    if (num == 0)
    {
        return 8; // CHAR_BIT在<climits>中定义，但在这里我们可以直接使用8
    }
    // 利用de Bruijn序列的查找表方法来计算前导零的个数
    // 下面的查找表是针对8位整数的，它假设了CHAR_BIT为8
    static const unsigned char deBruijnTable[32] = {
        0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 34, 20, 40,
        5, 17, 26, 38, 15, 46, 29, 44, 10, 31, 35, 51, 21, 54, 41, 58,
        // 仅需要以上这些，因为我们处理的是8位整数
    };
    // 通过位操作构造一个特殊的索引值
    num |= num >> 1;
    num |= num >> 2;
    num |= num >> 4;
    // 此时num的最低位的1及其之后的所有位都是1
    // 减去1，这样最低位的1就变成了0，而它之前的位（如果有的话）变成了1
    num = (num - 1) & ~num;
    // 使用de Bruijn序列查找表来找到前导零的个数
    // 注意：这里我们假设CHAR_BIT为8，所以索引是num * 0x077CB531 >> 27
    // 0x077CB531是一个针对8位整数的魔法数字，它是de Bruijn序列的哈希结果
    return deBruijnTable[(num * 0x077CB531U) >> 27];
}

template <int N2_31=0,int N32=0>
void func(){
    //T t;
    //t.test_print();
    for(int i=0;i<N2_31;i++){}
    for(int i=0;i<N32;++i){}
}


std::vector<char> input_char;
size_t read_file_to_memory(std::vector<char> &buffer, const std::string &filepath)
{
    // std::vector<char> buffer;
    std::ifstream file(filepath, std::ios::binary | std::ios::ate); // 以二进制模式打开并移动到文件末尾

    if (!file)
    {
        std::cerr << "无法打开文件: " << filepath << std::endl;
        // return buffer; // 返回一个空的 vector
        return 0;
    }

    // 获取文件大小
    std::streamsize size = file.tellg();

    // 移动到文件开头
    file.seekg(0, std::ios::beg);

    // 分配足够的内存
    buffer.resize(size);

    // 读取文件到内存
    if (!file.read(buffer.data(), size))
    {
        std::cerr << "读取文件时出错: " << filepath << std::endl;
        buffer.clear(); // 如果读取失败，则清除 vector
    }

    // 关闭文件
    file.close();

    printf("file byte size=%d long size=%d\n", size, size / 8);
    return size;
    // return buffer;
}
std::vector<double> dvec;
void read_from_file()
{
    FILE *fp_mtx;
    fp_mtx = fopen("E:\\code\\cpp\\other_git_project\\CSR2\\rajat31.mtx", "r");
    int row_num, col_num, nzz_num;
    fscanf(fp_mtx, "%d %d %d", &row_num, &col_num, &nzz_num);
    std::cout << "row_num = " << row_num << "col_num = " << col_num << "nzz_num = " << nzz_num << std::endl;
    dvec.resize(nzz_num);
    const int N = global_N;
    for (int i = 0; i < N; ++i)
    {
        int row, col;
        double nzz;
        fscanf(fp_mtx, "%d %d %lf", &row, &col, &nzz);
        dvec[i] = nzz;
    }
    printf("read finish\n");
}
void testavx()
{
    //__m512i temp=_mm512_set1_epi64(3);
    //__m512i res=_mm512_popcnt_epi64(temp);
    // printf("%d\n",_mm512_reduce_add_epi64(res));
}
int main()
{
    init_information();
    // global_N = (read_file_to_memory(input_char,"./mr") / 8);
    testavx();
    // srand(time(NULL));
    generate();
    int concurrency = std::max(std::thread::hardware_concurrency(), 1u);
    // printf("cpu core num = %d\n", concurrency);
    std::random_device rd;
    std::mt19937 gen(rd());
    // read_from_file();
    //   srand((unsigned int)time(NULL));
    const int N = global_N; // 128M 1G
    // std::vector<unsigned long long int> arr(N);//8GB
    for (int i = 0; i < N; i++)
    {
        // arr[i] = gen();
    }

    {
        int sum = 0;
        int b = rand() % 256;
        int c = rand() % 256;
        if (b <= 2)
            b = 2; // 2->255
        if (c <= 2)
            c = 2;
        double bi = 1.0 / b;
        double ci = 1.0 / c;
        auto time1 = std::chrono::system_clock::now();
        auto start = getcycle();
        // std::sort(arr.begin(), arr.end());
        unsigned int num0_5 = 0, num6_11 = 0, num12_17 = 0, num18_23 = 0, num24_29 = 0;
        unsigned int num30_35 = 0, num36_41 = 0, num42_47 = 0, num48_53 = 0, num54_59, num60_63 = 0;
        unsigned int numother1 = 0, numother2 = 0, numother3 = 0;
        unsigned long long int num1 = 0, num2 = 0, num3 = 0, num4 = 0, num5 = 0, num6 = 0, num7 = 0, num8 = 0;
        double sum_double = 0;
        unsigned int num5_0 = 0, num5_1 = 0, num5_2 = 0, num5_3 = 0, num5_4 = 0,
                     num5_5 = 0, num5_6 = 0, num5_7 = 0, num5_8 = 0, num5_9 = 0,
                     num5_10 = 0, num5_11 = 0, num5_rest4 = 0; // all is 13个
        unsigned int result4[4] = {0};
        unsigned long long int num = 0;
        // printf("start record--\n");
        if (0)
#pragma omp parallel for num_threads(8)                                                                           \
    reduction(| : num5_0) reduction(| : num5_1) reduction(| : num5_2) reduction(| : num5_3) reduction(| : num5_4) \
    reduction(| : num5_5) reduction(| : num5_6) reduction(| : num5_7) reduction(| : num5_8) reduction(| : num5_9) \
    reduction(| : num5_10) reduction(| : num5_11) reduction(| : num5_rest4)
            for (int i = 0; i < N; i++)
            {
                // sum_double+=arr[i];
                // V v;
                // v.ull.a=i;
                // unsigned long long int num = arr[i];
                unsigned long long int num = i;

                const unsigned int tmp = ((1u << 6) - 1);
                const unsigned int one = 1u;
                num5_0 |= (one << ((num >> (0 * 5)) & tmp));
                num5_1 |= (one << ((num >> (1 * 5)) & tmp));
                num5_2 |= (one << ((num >> (2 * 5)) & tmp));
                num5_3 |= (one << ((num >> (3 * 5)) & tmp));
                num5_4 |= (one << ((num >> (4 * 5)) & tmp));
                num5_5 |= (one << ((num >> (5 * 5)) & tmp));
                num5_6 |= (one << ((num >> (6 * 5)) & tmp));
                num5_7 |= (one << ((num >> (7 * 5)) & tmp));
                num5_8 |= (one << ((num >> (8 * 5)) & tmp));
                num5_9 |= (one << ((num >> (9 * 5)) & tmp));
                num5_10 |= (one << ((num >> (10 * 5)) & tmp));
                num5_11 |= (one << ((num >> (11 * 5)) & tmp));
                num5_rest4 |= (one << ((num >> (12 * 5)) & ((1u << 5) - 1)));

                // num54_59 |= (1<<( (num >> (9*5)) & ((1<<6)-1)));
                //  num0_5+=( (num >> (0*6)) & ((1<<6)-1)1);
                //  num6_11+=( (num >> (1*6)) & ((1<<6)-1)1);
                //  num12_17+=( (num >> (2*6)) & ((1<<6)-1)1);
                //  num18_23+=( (num >> (3*6)) & ((1<<6)-1)1);
                //  num24_29+=( (num >> (4*6)) & ((1<<6)-1)1);
                //  num30_35+=( (num >> (5*6)) & ((1<<6)-1)1);
                //  num36_41+=( (num >> (6*6)) & ((1<<6)-1)1);
                //  num42_47+=( (num >> (7*6)) & ((1<<6)-1)1);
                //  num48_53+=( (num >> (8*6)) & ((1<<6)-1)1);
                //  num54_59+=( (num >> (9*6)) & ((1<<6)-1)1);
                //  num1 |= ( (num >> (0*8)) & 0x11111111);
                //  num2 |= ( (num >> (1*8)) & 0x11111111);
                //  num3 |= ( (num >> (2*8)) & 0x11111111);
                //  num4 |= ( (num >> (3*8)) & 0x11111111);
                //  num5 |= ( (num >> (4*8)) & 0x11111111);
                //  num6 |= ( (num >> (5*8)) & 0x11111111);
                //  num7 |= ( (num >> (6*8)) & 0x11111111);
                //  num8 |= ( (num >> (7*8)) & 0x11111111);

                // sum  +=  (i%b);
                // double id=i;
                // sum  +=  (i-(int(i*bi))*b);
                // sum+=(i/b)%c;//68714492
                // int(a*b_inv) - (int(a*b_inv)*c_inv)*c ;
                // int d=int(i*bi);
                // sum += (d - (int(d * ci))*c);
            }
        auto end = getcycle();
        auto time2 = std::chrono::system_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(time2 - time1).count();
        std::cout << "duration cycle: " << end - start << "  time ns : " << duration << "  time ms : " << duration / 1e6 << " one number : " << 1.0 * duration / N << std::endl;
        printf("sum1=%d\n", num0_5 + num6_11 + num12_17 + num18_23 + num24_29 + num30_35 + num36_41 + num42_47 + num48_53 + num54_59 + numother1 + numother2 + numother3);
        printf("sum1=%llu\n", num1 + num2 + num3 + num4 + num5 + num6 + num7 + num8);
        printf("sum_double=%lf\n", sum_double);
        printf("num5_0=%u\n", num5_0);
        printf("sum_num5=%u\n", num5_0 + num5_1 + num5_2 + num5_3 + num5_4 + num5_5 + num5_6 + num5_7 + num5_8 + num5_9 + num5_10 + num5_11 + num5_rest4 + result4[0] + result4[1] + result4[2] + result4[3]);
    }

    {
        int sum = 0;
        uint64_t num;
        auto time1 = std::chrono::system_clock::now();
        auto start = getcycle();
        for (int i = 1; i <= 256; i++)
        {
            // int num=i%256;
            // sum  +=   ceil(log2(i));
            // printf("i=%d,c1=%d,c2=%d\n", i , int(ceil(log2(i))), 8 - countLeadingZeros(  (unsigned char)(i-1)));
            // printf("%d,",int(ceil(log2(i))));
        }
        auto end = getcycle();
        auto time2 = std::chrono::system_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(time2 - time1).count();
        // std::cout << "duration cycle: " << end - start << "  time ns : " << duration << " one number : " << double(duration) / N << std::endl;
        // printf("sum=%d,sum=%lu\n", sum, num);
    }

    {
        //----init----
        unsigned char charHas1_num[256] = {0};     // 0-255的数，该数二进制中有多少个1。
        unsigned char char_1_index[256][8] = {0};  // 8*256;  记录每个char num中1的位置   2KB ,可压缩为一半空间，但是取数据时不好写
        unsigned char count_char_1_sum[256] = {0}; // 记录每个数字中1的个数  0-8用4bit存 , 可压缩为一半空间128B

        unsigned char count_ushort_1_sum[1 << 16] = {0}; // 64KB
        unsigned char ushort_1_index[1 << 16][16] = {0}; // 1M

        for (int i = 0; i < (1 << 8); ++i)
        {
            int num = 0;
            int countIndex = 0;
            for (int j = 0; j < 8; ++j)
            {
                if (i & (1 << j))
                {
                    num++;
                    char_1_index[i][countIndex++] = j;
                }
            }
            count_char_1_sum[i] = countIndex;
            // if (i % 2 == 0)
            //     count_char_1_sum[i / 2] = countIndex;
            // else
            //     count_char_1_sum[i / 2] += countIndex * (1 << 4);
            charHas1_num[i] = num;
        }
        for (int i = 0; i < (1 << 16); ++i)
        {
            int countIndex = 0;
            for (int j = 0; j < 16; ++j)
            {
                if (i & (1 << j))
                {
                    ushort_1_index[i][countIndex++] = j;
                }
            }
            count_ushort_1_sum[i] = countIndex;
        }
        //-----init-----

        // 2*8=16KB
        // char array[8192];  // 8192,     8192B=8KB
        // char array2[8192]; // 8192,     8192B=8KB

#if 1
        std::vector<double> input;
        input.reserve(N);
        // #pragma omp parallel for num_threads(8)
        for (int i = 0; i < N; i++)
            input[i] = gen();
#else
        double *input = (double *)input_char.data();
#endif
        // 8*32B=256Byte   可以合并到一个数组中。
        // 数组表示为256bit，第i个bit为1表示出现过i
        alignas(64) unsigned char isExistRange0_255_12345678[8 * 32] = {0};
        unsigned char *const isExistRange0_255_1 = &isExistRange0_255_12345678[0 * 32];
        unsigned char *const isExistRange0_255_2 = &isExistRange0_255_12345678[1 * 32];
        unsigned char *const isExistRange0_255_3 = &isExistRange0_255_12345678[2 * 32];
        unsigned char *const isExistRange0_255_4 = &isExistRange0_255_12345678[3 * 32];
        unsigned char *const isExistRange0_255_5 = &isExistRange0_255_12345678[4 * 32];
        unsigned char *const isExistRange0_255_6 = &isExistRange0_255_12345678[5 * 32];
        unsigned char *const isExistRange0_255_7 = &isExistRange0_255_12345678[6 * 32];
        unsigned char *const isExistRange0_255_8 = &isExistRange0_255_12345678[7 * 32];
        // alignas(64) unsigned char isExistRange0_255_1[32] = {0}; // 256bit
        // alignas(64) unsigned char isExistRange0_255_2[32] = {0}; // 256
        // alignas(64) unsigned char isExistRange0_255_3[32] = {0}; // 256
        // alignas(64) unsigned char isExistRange0_255_4[32] = {0}; // 256
        // alignas(64) unsigned char isExistRange0_255_5[32] = {0}; // 256
        // alignas(64) unsigned char isExistRange0_255_6[32] = {0}; // 256
        // alignas(64) unsigned char isExistRange0_255_7[32] = {0}; // 256
        // alignas(64) unsigned char isExistRange0_255_8[32] = {0}; // 256

        // alignas(64) unsigned char isExistRange0_255_12[64] = {0}; // 512bit
        // alignas(64) unsigned char isExistRange0_255_34[64] = {0}; // 512bit
        // alignas(64) unsigned char isExistRange0_255_56[64] = {0}; // 512bit
        // alignas(64) unsigned char isExistRange0_255_78[64] = {0}; // 512bit
        //  2KB 为了速度，增加空间占用。
        alignas(64) unsigned char isExistRange0_255_1_12345678[8 * 256] = {0};
        unsigned char *const isExistRange0_255_1_1 = &isExistRange0_255_1_12345678[0 * 256];
        unsigned char *const isExistRange0_255_2_2 = &isExistRange0_255_1_12345678[1 * 256];
        unsigned char *const isExistRange0_255_3_3 = &isExistRange0_255_1_12345678[2 * 256];
        unsigned char *const isExistRange0_255_4_4 = &isExistRange0_255_1_12345678[3 * 256];
        unsigned char *const isExistRange0_255_5_5 = &isExistRange0_255_1_12345678[4 * 256];
        unsigned char *const isExistRange0_255_6_6 = &isExistRange0_255_1_12345678[5 * 256];
        unsigned char *const isExistRange0_255_7_7 = &isExistRange0_255_1_12345678[6 * 256];
        unsigned char *const isExistRange0_255_8_8 = &isExistRange0_255_1_12345678[7 * 256];

        alignas(64) unsigned char isExistRange0_255_4bit_16[16 * 16] = {0};        // 1 for exist , 0 for not exist
        alignas(64) unsigned char stroageEncounterNum_4bit_16[16][16] = {0};       // 存储出现过的num(range:0-15)
        alignas(64) unsigned char EncounterNum_to_EncodeNum_4bit_16[16][16] = {0}; // 存储出现过的num压缩时的序号。

        // alignas(64)unsigned char isExistRange0_255_1_1[256] = {0};
        // alignas(64)unsigned char isExistRange0_255_2_2[256] = {0};
        // alignas(64)unsigned char isExistRange0_255_3_3[256] = {0};
        // alignas(64)unsigned char isExistRange0_255_4_4[256] = {0};
        // alignas(64)unsigned char isExistRange0_255_5_5[256] = {0};
        // alignas(64)unsigned char isExistRange0_255_6_6[256] = {0};
        // alignas(64)unsigned char isExistRange0_255_7_7[256] = {0};
        // alignas(64)unsigned char isExistRange0_255_8_8[256] = {0};

        unsigned long long int *const ptr1 = (unsigned long long int *)isExistRange0_255_1;
        unsigned long long int *const ptr2 = (unsigned long long int *)isExistRange0_255_2;
        unsigned long long int *const ptr3 = (unsigned long long int *)isExistRange0_255_3;
        unsigned long long int *const ptr4 = (unsigned long long int *)isExistRange0_255_4;
        unsigned long long int *const ptr5 = (unsigned long long int *)isExistRange0_255_5;
        unsigned long long int *const ptr6 = (unsigned long long int *)isExistRange0_255_6;
        unsigned long long int *const ptr7 = (unsigned long long int *)isExistRange0_255_7;
        unsigned long long int *const ptr8 = (unsigned long long int *)isExistRange0_255_8;

        // 256B*8=2048B=2KB
        // 存储出现过的num(range:0-255)
        alignas(64) unsigned char stroageEncounterNum_12345678[8 * 256] = {0};
        unsigned char *const stroageEncounterNum_1 = &stroageEncounterNum_12345678[0 * 256]; //
        unsigned char *const stroageEncounterNum_2 = &stroageEncounterNum_12345678[1 * 256]; //
        unsigned char *const stroageEncounterNum_3 = &stroageEncounterNum_12345678[2 * 256]; //
        unsigned char *const stroageEncounterNum_4 = &stroageEncounterNum_12345678[3 * 256]; //
        unsigned char *const stroageEncounterNum_5 = &stroageEncounterNum_12345678[4 * 256]; //
        unsigned char *const stroageEncounterNum_6 = &stroageEncounterNum_12345678[5 * 256]; //
        unsigned char *const stroageEncounterNum_7 = &stroageEncounterNum_12345678[6 * 256]; //
        unsigned char *const stroageEncounterNum_8 = &stroageEncounterNum_12345678[7 * 256]; //
        // alignas(64)unsigned char stroageEncounterNum_1[256] = {0}; //
        // alignas(64)unsigned char stroageEncounterNum_2[256] = {0}; //
        // alignas(64)unsigned char stroageEncounterNum_3[256] = {0}; //
        // alignas(64)unsigned char stroageEncounterNum_4[256] = {0}; //
        // alignas(64)unsigned char stroageEncounterNum_5[256] = {0}; //
        // alignas(64)unsigned char stroageEncounterNum_6[256] = {0}; //
        // alignas(64)unsigned char stroageEncounterNum_7[256] = {0}; //
        // alignas(64)unsigned char stroageEncounterNum_8[256] = {0}; //

        // 存储出现过的num压缩时的序号。2KB
        alignas(64) unsigned char EncounterNum_to_EncodeNum_12345678[8 * 256] = {0}; //
        unsigned char *const EncounterNum_to_EncodeNum_1 = &EncounterNum_to_EncodeNum_12345678[0 * 256];
        unsigned char *const EncounterNum_to_EncodeNum_2 = &EncounterNum_to_EncodeNum_12345678[1 * 256];
        unsigned char *const EncounterNum_to_EncodeNum_3 = &EncounterNum_to_EncodeNum_12345678[2 * 256];
        unsigned char *const EncounterNum_to_EncodeNum_4 = &EncounterNum_to_EncodeNum_12345678[3 * 256];
        unsigned char *const EncounterNum_to_EncodeNum_5 = &EncounterNum_to_EncodeNum_12345678[4 * 256];
        unsigned char *const EncounterNum_to_EncodeNum_6 = &EncounterNum_to_EncodeNum_12345678[5 * 256];
        unsigned char *const EncounterNum_to_EncodeNum_7 = &EncounterNum_to_EncodeNum_12345678[6 * 256];
        unsigned char *const EncounterNum_to_EncodeNum_8 = &EncounterNum_to_EncodeNum_12345678[7 * 256];
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_1[256] = {0}; //
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_2[256] = {0}; //
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_3[256] = {0}; //
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_4[256] = {0}; //
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_5[256] = {0}; //
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_6[256] = {0}; //
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_7[256] = {0}; //
        // alignas(64)unsigned char EncounterNum_to_EncodeNum_8[256] = {0}; //
        for (int i = 0; i < 256; ++i)
        {
            EncounterNum_to_EncodeNum_1[i] = i;
            EncounterNum_to_EncodeNum_2[i] = i;
            EncounterNum_to_EncodeNum_3[i] = i;
            EncounterNum_to_EncodeNum_4[i] = i;
            EncounterNum_to_EncodeNum_5[i] = i;
            EncounterNum_to_EncodeNum_6[i] = i;
            EncounterNum_to_EncodeNum_7[i] = i;
            EncounterNum_to_EncodeNum_8[i] = i;
        }

        // set1
        auto time1 = std::chrono::system_clock::now();
        auto cycle1 = getcycle();
        memset(isExistRange0_255_1, 0, 32);
        memset(isExistRange0_255_2, 0, 32);
        memset(isExistRange0_255_3, 0, 32);
        memset(isExistRange0_255_4, 0, 32);
        memset(isExistRange0_255_5, 0, 32);
        memset(isExistRange0_255_6, 0, 32);
        memset(isExistRange0_255_7, 0, 32);
        memset(isExistRange0_255_8, 0, 32);

        auto cycle2 = getcycle();
        auto time_cycle2_start = std::chrono::system_clock::now();
        // avx512f的实现方法
        const __m512 m512_zero = _mm512_setzero(); // 0
        __m512i m512_one = _mm512_set1_epi64(1);   // 0
        __m512i m512_12 = _mm512_set1_epi64(0);    // 0
        __m512i m512_34 = _mm512_set1_epi64(0);    // 0
        __m512i m512_56 = _mm512_set1_epi64(0);    // 0
        __m512i m512_78 = _mm512_set1_epi64(0);    // 0
        __m256i m256_1 = _mm256_set_epi64x(0, 0, 0, 0);
        __m256i m256_2 = _mm256_set_epi64x(0, 0, 0, 0);
        __m256i m256_3 = _mm256_set_epi64x(0, 0, 0, 0);
        __m256i m256_4 = _mm256_set_epi64x(0, 0, 0, 0);
        __m256i m256_5 = _mm256_set_epi64x(0, 0, 0, 0);
        __m256i m256_6 = _mm256_set_epi64x(0, 0, 0, 0);
        __m256i m256_7 = _mm256_set_epi64x(0, 0, 0, 0);
        __m256i m256_8 = _mm256_set_epi64x(0, 0, 0, 0);
        const __m256i m256_one = _mm256_set1_epi64x(1); // 0
        // __m256i m256_2 = _mm256_set_epi64x(0,1,0,1);
        // __m256i m256_3 = _mm256_set_epi64x(0,1,0,1);
        // __m256i m256_4 = _mm256_set_epi64x(0,1,0,1);
        // __m256i m256_5 = _mm256_set_epi64x(0,1,0,1);
        // __m256i m256_6 = _mm256_set_epi64x(0,1,0,1);
        // __m256i m256_7 = _mm256_set_epi64x(0,1,0,1);
        // __m256i m256_8 = _mm256_set_epi64x(0,1,0,1);
        //__mmask8 masknum;
        //__builtin_prefetch(isExistRange0_255_1_12345678,1,3);//write,l1 cache;
        unsigned long long int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
        unsigned long long int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
        unsigned long long int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
        unsigned long long int d1 = 0, d2 = 0, d3 = 0, d4 = 0;
        unsigned long long int e1 = 0, e2 = 0, e3 = 0, e4 = 0;
        unsigned long long int f1 = 0, f2 = 0, f3 = 0, f4 = 0;
        unsigned long long int g1 = 0, g2 = 0, g3 = 0, g4 = 0;
        unsigned long long int h1 = 0, h2 = 0, h3 = 0, h4 = 0;
        unsigned long long int num0_5 = 0, num6_11 = 0, num12_17 = 0, num18_23 = 0, num24_30 = 0;
        unsigned long long int num31_35 = 0, num36_41 = 0, num42_47 = 0, num48_53 = 0, num54_60, num61_64 = 0;
        unsigned int num5_0 = 0, num5_1 = 0, num5_2 = 0, num5_3 = 0, num5_4 = 0,
                     num5_5 = 0, num5_6 = 0, num5_7 = 0, num5_8 = 0, num5_9 = 0,
                     num5_10 = 0, num5_11 = 0, num5_rest4 = 0; // all is 13个
        unsigned short isExistRange0_15[16] = {0};             // 16bit*16=32byte

        // auto myreductionFunction =[](unsigned char  * A,unsigned char * B,int length=256){
        //     for(int i=0;i<length;i++){
        //         A[i] += B[i];
        //     }
        // };
        class MyReductionFunctionType
        {
        public:
            unsigned char A[256];
            MyReductionFunctionType()
            {
                // A=(unsigned char*)malloc(sizeof(unsigned char)*256);
                memset(A, 0, sizeof(MyReductionFunctionType));
            };
            void myreductionFunction(MyReductionFunctionType B)
            {
                for (int i = 0; i < 256; ++i)
                {
                    A[i] = A[i] | B.A[i]; // 0 0 -> 0 other 1
                }
            }
            // unsigned char operator[](unsigned char i){return A[i];}
            ~MyReductionFunctionType()
            {
                // static unsigned char num=0;
                // printf("call free=%d\n",++num);//call 72 times
                // free(A);
            }
        };
        MyReductionFunctionType isExistRange0_255_1_1_OMP,
            isExistRange0_255_2_2_OMP,
            isExistRange0_255_3_3_OMP,
            isExistRange0_255_4_4_OMP,
            isExistRange0_255_5_5_OMP,
            isExistRange0_255_6_6_OMP,
            isExistRange0_255_7_7_OMP,
            isExistRange0_255_8_8_OMP;
#pragma omp declare reduction(myreduction:MyReductionFunctionType : omp_out.myreductionFunction(omp_in)) initializer(omp_priv = MyReductionFunctionType())
        // #pragma omp parallel for num_threads(1) \
//                          reduction(|:num5_0) reduction(|:num5_1) reduction(|:num5_2) reduction(|:num5_3) reduction(|:num5_4) \
//                          reduction(|:num5_5) reduction(|:num5_6) reduction(|:num5_7) reduction(|:num5_8) reduction(|:num5_9) \
//                          reduction(|:num5_10)reduction(|:num5_11)reduction(|:num5_rest4)\
//                          reduction(myreduction:isExistRange0_255_1_1_OMP)\
//                          reduction(myreduction:isExistRange0_255_2_2_OMP)\
//                          reduction(myreduction:isExistRange0_255_3_3_OMP)\
//                          reduction(myreduction:isExistRange0_255_4_4_OMP)\
//                          reduction(myreduction:isExistRange0_255_5_5_OMP)\
//                          reduction(myreduction:isExistRange0_255_6_6_OMP)\
//                          reduction(myreduction:isExistRange0_255_7_7_OMP)\
//                          reduction(myreduction:isExistRange0_255_8_8_OMP)
        // printf("start record\n");
         // #pragma omp parallel for num_threads(8)\
        reduction(|:isExistRange0_15[0]) reduction(|:isExistRange0_15[1])
        // reduction(|:isExistRange0_15[0]) reduction(|:isExistRange0_15[1]) reduction(|:isExistRange0_15[2]) reduction(|:isExistRange0_15[3])\
        // reduction(|:isExistRange0_15[4]) reduction(|:isExistRange0_15[5]) reduction(|:isExistRange0_15[6]) reduction(|:isExistRange0_15[7])\
        // reduction(|:isExistRange0_15[8]) reduction(|:isExistRange0_15[9]) reduction(|:isExistRange0_15[10]) reduction(|:isExistRange0_15[11])\
        // reduction(|:isExistRange0_15[12]) reduction(|:isExistRange0_15[13]) reduction(|:isExistRange0_15[14]) reduction(|:isExistRange0_15[15])
        for (int i = 1; i <= N; ++i)
        {
            // openmp | recdution init value is 0
            // if N less than a num then sequence
            V v;
            v.dou.a = input[i - 1];
            unsigned long long int num = v.ll.a;
            // double dnum = input[i];
            //  printf("i=%d,dnum=%lf\n", i, dnum);
            // long long int num = *(long long int *)(&dnum);

            // isExistRange0_255_1[((num >> 56) & 255) / 8] |= (1 << (((num >> 56) & 255) % 8));
            // isExistRange0_255_2[((num >> 48) & 255) / 8] |= (1 << (((num >> 48) & 255) % 8));
            // isExistRange0_255_3[((num >> 40) & 255) / 8] |= (1 << (((num >> 40) & 255) % 8));
            // isExistRange0_255_4[((num >> 32) & 255) / 8] |= (1 << (((num >> 32) & 255) % 8));
            // isExistRange0_255_5[((num >> 24) & 255) / 8] |= (1 << (((num >> 24) & 255) % 8));
            // isExistRange0_255_6[((num >> 16) & 255) / 8] |= (1 << (((num >> 16) & 255) % 8));
            // isExistRange0_255_7[((num >> 8) & 255) / 8] |= (1 << (((num >> 8) & 255) % 8));
            // isExistRange0_255_8[((num >> 0) & 255) / 8] |= (1 << (((num >> 0) & 255) % 8));

            // isExistRange0_255_1_1[((num >> 56) & 255)]=1;
            // isExistRange0_255_2_2[((num >> 48) & 255)]=1;
            // isExistRange0_255_3_3[((num >> 40) & 255)]=1;
            // isExistRange0_255_4_4[((num >> 32) & 255)]=1;
            // isExistRange0_255_5_5[((num >> 24) & 255)]=1;
            // isExistRange0_255_6_6[((num >> 16) & 255)]=1;
            // isExistRange0_255_7_7[((num >> 8) & 255)]=1;
            // isExistRange0_255_8_8[((num) & 255)]=1;

            // 利用avx512指令太慢,
            // __mmask8 k12 = (1 << (4 + v.char8.a / 64)) + (1 << (v.char8.b / 64));
            // __m256i a1 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.a % 64);
            // __m256i a2 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.b % 64);
            // __m512i a12 = _mm512_inserti64x4(_mm512_setzero_si512(), a2, 0);
            // a12 = _mm512_inserti64x4(a12, a1, 1);
            // __m512i or12 = _mm512_mask_blend_epi64(k12, m512_zero, a12);
            // m512_12 = _mm512_or_si512(m512_12, or12);

            // __mmask8 k34 = (1 << (4 + v.char8.c / 64)) + (1 << (v.char8.d / 64));
            // __m256i a3 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.c % 64);
            // __m256i a4 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.d % 64);
            // __m512i a34 = _mm512_inserti64x4(_mm512_setzero_si512(), a4, 0);
            // a34 = _mm512_inserti64x4(a34, a3, 1);
            // __m512i or34 = _mm512_mask_blend_epi64(k34, m512_zero, a34);
            // m512_34 = _mm512_or_si512(m512_34, or34);

            // __mmask8 k56 = (1 << (4 + v.char8.e / 64)) + (1 << (v.char8.f / 64));
            // __m256i a5 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.e % 64);
            // __m256i a6 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.f % 64);
            // __m512i a56 = _mm512_inserti64x4(_mm512_setzero_si512(), a6, 0);
            // a56 = _mm512_inserti64x4(a56, a5, 1);
            // __m512i or56 = _mm512_mask_blend_epi64(k56, m512_zero, a56);
            // m512_56 = _mm512_or_si512(m512_56, or56);

            // __mmask8 k78 = (1 << (4 + v.char8.g / 64)) + (1 << (v.char8.h / 64));
            // __m256i a7 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.g % 64);
            // __m256i a8 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.h % 64);
            // __m512i a78 = _mm512_inserti64x4(_mm512_setzero_si512(), a8, 0);
            // a78 = _mm512_inserti64x4(a78, a7, 1);
            // __m512i or78 = _mm512_mask_blend_epi64(k78, m512_zero, a78);
            // m512_78 = _mm512_or_si512(m512_78, or78);

            //----------------------------------------------------------------
            // const __m512i m512_zero = _mm512_set1_epi64(0); // 0
            // __mmask8 k12 = (1 << (4 + v.char8.a / 64)) + (1 << (v.char8.b / 64));
            // __mmask8 k34 = (1 << (4 + v.char8.c / 64)) + (1 << (v.char8.d / 64));
            // __mmask8 k56 = (1 << (4 + v.char8.e / 64)) + (1 << (v.char8.f / 64));
            // __mmask8 k78 = (1 << (4 + v.char8.g / 64)) + (1 << (v.char8.h / 64));

            // __m256i a1 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.a % 64);
            // __m256i a2 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.b % 64);
            // __m256i a3 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.c % 64);
            // __m256i a4 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.d % 64);
            // __m256i a5 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.e % 64);
            // __m256i a6 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.f % 64);
            // __m256i a7 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.g % 64);
            // __m256i a8 = _mm256_slli_epi64(_mm256_set1_epi64x(1), v.char8.h % 64);

            // __m512i a12 = _mm512_inserti64x4(_mm512_setzero_si512(), a2, 0);
            // __m512i a34 = _mm512_inserti64x4(_mm512_setzero_si512(), a4, 0);
            // __m512i a56 = _mm512_inserti64x4(_mm512_setzero_si512(), a6, 0);
            // __m512i a78 = _mm512_inserti64x4(_mm512_setzero_si512(), a8, 0);

            // a12 = _mm512_inserti64x4(a12, a1, 1);
            // a34 = _mm512_inserti64x4(a34, a3, 1);
            // a56 = _mm512_inserti64x4(a56, a5, 1);
            // a78 = _mm512_inserti64x4(a78, a7, 1);

            // __m512i or12 = _mm512_mask_blend_epi64(k12, m512_zero, a12);
            // __m512i or34 = _mm512_mask_blend_epi64(k34, m512_zero, a34);
            // __m512i or56 = _mm512_mask_blend_epi64(k56, m512_zero, a56);
            // __m512i or78 = _mm512_mask_blend_epi64(k78, m512_zero, a78);

            // m512_12 = _mm512_or_si512(m512_12, or12);
            // m512_34 = _mm512_or_si512(m512_34, or34);
            // m512_56 = _mm512_or_si512(m512_56, or56);
            // m512_78 = _mm512_or_si512(m512_78, or78);
            //---------------------------------------------------------------

            // a1 |= ((1ull<<(v.char8.a%64))*((v.char8.a&0b11000000)==0b00000000));
            // a2 |= ((1ull<<(v.char8.a%64))*((v.char8.a&0b11000000)==0b01000000));
            // a3 |= ((1ull<<(v.char8.a%64))*((v.char8.a&0b11000000)==0b10000000));
            // a4 |= ((1ull<<(v.char8.a%64))*((v.char8.a&0b11000000)==0b11000000));

            // __mmask8 mask1=1<<(v.char8.a/64);
            // __mmask8 mask2=1<<(v.char8.b/64);
            // __mmask8 mask3=1<<(v.char8.c/64);
            // __mmask8 mask4=1<<(v.char8.d/64);
            // __mmask8 mask5=1<<(v.char8.e/64);
            // __mmask8 mask6=1<<(v.char8.f/64);
            // __mmask8 mask7=1<<(v.char8.g/64);
            // __mmask8 mask8=1<<(v.char8.h/64);

            // __m256i tmp1=_mm256_slli_epi64(m256_one,v.char8.a%64);
            // __m256i tmp2=_mm256_slli_epi64(m256_one,v.char8.b%64);
            // __m256i tmp3=_mm256_slli_epi64(m256_one,v.char8.c%64);
            // __m256i tmp4=_mm256_slli_epi64(m256_one,v.char8.d%64);
            // __m256i tmp5=_mm256_slli_epi64(m256_one,v.char8.e%64);
            // __m256i tmp6=_mm256_slli_epi64(m256_one,v.char8.f%64);
            // __m256i tmp7=_mm256_slli_epi64(m256_one,v.char8.g%64);
            // __m256i tmp8=_mm256_slli_epi64(m256_one,v.char8.h%64);

            // m256_1 = _mm256_mask_or_epi64(m256_1,mask1,m256_1,tmp1);
            // m256_2 = _mm256_mask_or_epi64(m256_2,mask2,m256_2,tmp2);
            // m256_3 = _mm256_mask_or_epi64(m256_3,mask3,m256_3,tmp3);
            // m256_4 = _mm256_mask_or_epi64(m256_4,mask4,m256_4,tmp4);
            // m256_5 = _mm256_mask_or_epi64(m256_5,mask5,m256_5,tmp5);
            // m256_6 = _mm256_mask_or_epi64(m256_6,mask6,m256_6,tmp6);
            // m256_7 = _mm256_mask_or_epi64(m256_7,mask7,m256_7,tmp7);
            // m256_8 = _mm256_mask_or_epi64(m256_8,mask8,m256_8,tmp8);

            // m256_1 = _mm256_mask_or_epi64(m256_1,1<<(v.char8.a/64),m256_1,_mm256_slli_epi64(m256_one,v.char8.a%64));
            // m256_2 = _mm256_mask_or_epi64(m256_2,1<<(v.char8.b/64),m256_2,_mm256_slli_epi64(m256_one,v.char8.b%64));
            // m256_3 = _mm256_mask_or_epi64(m256_3,1<<(v.char8.c/64),m256_3,_mm256_slli_epi64(m256_one,v.char8.c%64));
            // m256_4 = _mm256_mask_or_epi64(m256_4,1<<(v.char8.d/64),m256_4,_mm256_slli_epi64(m256_one,v.char8.d%64));
            // m256_5 = _mm256_mask_or_epi64(m256_5,1<<(v.char8.e/64),m256_5,_mm256_slli_epi64(m256_one,v.char8.e%64));
            // m256_6 = _mm256_mask_or_epi64(m256_6,1<<(v.char8.f/64),m256_6,_mm256_slli_epi64(m256_one,v.char8.f%64));
            // m256_7 = _mm256_mask_or_epi64(m256_7,1<<(v.char8.g/64),m256_7,_mm256_slli_epi64(m256_one,v.char8.g%64));
            // m256_8 = _mm256_mask_or_epi64(m256_8,1<<(v.char8.h/64),m256_8,_mm256_slli_epi64(m256_one,v.char8.h%64));

            // if(!isExistRange0_255_1_1[v.char8.a])isExistRange0_255_1_1[v.char8.a] = 1;//0.2ns 1cycle
            // if(!isExistRange0_255_2_2[v.char8.b])isExistRange0_255_2_2[v.char8.b] = 1;
            // if(!isExistRange0_255_3_3[v.char8.c])isExistRange0_255_3_3[v.char8.c] = 1;
            // if(!isExistRange0_255_4_4[v.char8.d])isExistRange0_255_4_4[v.char8.d] = 1;
            // if(!isExistRange0_255_5_5[v.char8.e])isExistRange0_255_5_5[v.char8.e] = 1;
            // if(!isExistRange0_255_6_6[v.char8.f])isExistRange0_255_6_6[v.char8.f] = 1;
            // if(!isExistRange0_255_7_7[v.char8.g])isExistRange0_255_7_7[v.char8.g] = 1;
            // if(!isExistRange0_255_8_8[v.char8.h])isExistRange0_255_8_8[v.char8.h] = 1;

            // isExistRange0_255_1_1[v.char8.a] = 1;//0.2ns 1cycle
            // isExistRange0_255_2_2[v.char8.b] = 1;
            // isExistRange0_255_3_3[v.char8.c] = 1;
            // isExistRange0_255_4_4[v.char8.d] = 1;
            // isExistRange0_255_5_5[v.char8.e] = 1;
            // isExistRange0_255_6_6[v.char8.f] = 1;
            // isExistRange0_255_7_7[v.char8.g] = 1;
            // isExistRange0_255_8_8[v.char8.h] = 1;

            // isExistRange0_255_1_1_OMP.A[v.char8.a] = (unsigned char)1;//0.2ns 1cycle
            // isExistRange0_255_2_2_OMP.A[v.char8.b] = (unsigned char)1;
            // isExistRange0_255_3_3_OMP.A[v.char8.c] = (unsigned char)1;
            // isExistRange0_255_4_4_OMP.A[v.char8.d] = (unsigned char)1;
            // isExistRange0_255_5_5_OMP.A[v.char8.e] = (unsigned char)1;
            // isExistRange0_255_6_6_OMP.A[v.char8.f] = (unsigned char)1;
            // isExistRange0_255_7_7_OMP.A[v.char8.g] = (unsigned char)1;
            // isExistRange0_255_8_8_OMP.A[v.char8.h] = (unsigned char)1;

            // 3 cycle
            //  const unsigned int tmp=((1u<<5)-1);//0x0001 1111
            //  const unsigned int one = 1u;
            //  num5_0 |= (one<<( (num >> (64-1*5)) & tmp));//record 5 bit
            //  num5_1 |= (one<<( (num >> (64-2*5)) & tmp));
            //  num5_2 |= (one<<( (num >> (64-3*5)) & tmp));
            //  num5_3 |= (one<<( (num >> (64-4*5)) & tmp));
            //  num5_4 |= (one<<( (num >> (64-5*5)) & tmp));
            //  num5_5 |= (one<<( (num >> (64-6*5)) & tmp));
            //  num5_6 |= (one<<( (num >> (64-7*5)) & tmp));
            //  num5_7 |= (one<<( (num >> (64-8*5)) & tmp));
            //  num5_8 |= (one<<( (num >> (64-9*5)) & tmp));
            //  num5_9 |= (one<<( (num >> (64-10*5)) & tmp));
            //  num5_10 |= (one<<( (num >> (64-11*5)) & tmp));
            //  num5_11 |= (one<<( (num >> (64-12*5)) & tmp));
            //  num5_rest4 |= (one<<( (num >> (0)) & ((1u<<4)-1)));

            // const unsigned short tmp4=((1u<<4)-1);//0x0000 1111
            // const unsigned short one4 = 1u;
            for (int j = 0; j < 16; ++j)
            {
                isExistRange0_15[j] |= (1u << ((num >> (60 - j * 4)) & ((1u << 4) - 1)));
            }

            // V v1;
            // v1.dou.a = i+1;
            // long long int num = v1.ll.a;
        }
        for (int i = 0; i < 256; ++i)
        {
            // isExistRange0_255_1_1[i]=isExistRange0_255_1_1_OMP.A[i];
            // isExistRange0_255_2_2[i]=isExistRange0_255_2_2_OMP.A[i];
            // isExistRange0_255_3_3[i]=isExistRange0_255_3_3_OMP.A[i];
            // isExistRange0_255_4_4[i]=isExistRange0_255_4_4_OMP.A[i];
            // isExistRange0_255_5_5[i]=isExistRange0_255_5_5_OMP.A[i];
            // isExistRange0_255_6_6[i]=isExistRange0_255_6_6_OMP.A[i];
            // isExistRange0_255_7_7[i]=isExistRange0_255_7_7_OMP.A[i];
            // isExistRange0_255_8_8[i]=isExistRange0_255_8_8_OMP.A[i];
        }
        // printf("run here\n");
        for (int i = 0; i < 64; ++i)
        {
            // isExistRange0_255_1_1[i+64*0] = (a1 & (1ull<<i));
            // isExistRange0_255_1_1[i+64*1] = (a2 & (1ull<<i));
            // isExistRange0_255_1_1[i+64*2] = (a3 & (1ull<<i));
            // isExistRange0_255_1_1[i+64*3] = (a4 & (1ull<<i));
        }
        // unsigned long int sum5_0=0,sum5_1=0,sum5_2=0,sum5_3=0,sum5_4=0,sum5_5=0,sum5_6=0,sum5_7=0,sum5_8=0,sum5_9=0,sum5_10=0,sum5_11=0,sum5_rest4=0;
        // for(int i=0;i<32;++i){
        //     sum5_0 += ((num5_0>>i) & 1u);//记录共出现了多少种情况。
        //     sum5_1 += ((num5_1>>i) & 1u);
        //     sum5_2 += ((num5_2>>i) & 1u);
        //     sum5_3 += ((num5_3>>i) & 1u);
        //     sum5_4 += ((num5_4>>i) & 1u);
        //     sum5_5 += ((num5_5>>i) & 1u);
        //     sum5_6 += ((num5_6>>i) & 1u);
        //     sum5_7 += ((num5_7>>i) & 1u);
        //     sum5_8 += ((num5_8>>i) & 1u);
        //     sum5_9 += ((num5_9>>i) & 1u);
        //     sum5_10 += ((num5_10>>i) & 1u);
        //     sum5_11 += ((num5_11>>i) & 1u);
        // }
        // for(int i=0;i<16;++i){
        //     sum5_rest4 += ((num5_rest4>>i) & 1u);
        // }
        // printf("sum5_0=%lu\n",sum5_0);
        // printf("sum5_1=%lu\n",sum5_1);
        // printf("sum5_2=%lu\n",sum5_2);
        // printf("sum5_3=%lu\n",sum5_3);
        // printf("sum5_4=%lu\n",sum5_4);
        // printf("sum5_5=%lu\n",sum5_5);
        // printf("sum5_6=%lu\n",sum5_6);
        // printf("sum5_7=%lu\n",sum5_7);
        // printf("sum5_8=%lu\n",sum5_8);
        // printf("sum5_9=%lu\n",sum5_9);
        // printf("sum5_10=%lu\n",sum5_10);
        // printf("sum5_11=%lu\n",sum5_11);
        // printf("sum5_rest4=%lu\n",sum5_rest4);
        // //计算最少所需的bit数。这个函数需要优化
        // printf("sum5_min_bit=%d\n",int(ceil(log2( sum5_0 * sum5_1 * sum5_2 * sum5_3 * sum5_4 * sum5_5 * sum5_6 * sum5_7 * sum5_8 * sum5_9 * sum5_10 * sum5_11 * sum5_rest4))));

        for (int i = 0; i < 4; ++i)
        {
            // unsigned long long int n1 = 0;
            // unsigned long long int n2 = 0;
            // unsigned long long int n3 = 0;
            // unsigned long long int n4 = 0;
            // unsigned long long int n5 = 0;
            // unsigned long long int n6 = 0;
            // unsigned long long int n7 = 0;
            // unsigned long long int n8 = 0;
            // for (int j = 0; j < 64; ++j)
            // {
            //     n1 += ((unsigned long long int)isExistRange0_255_1_1[i * 64 + j] << j);
            //     n2 += ((unsigned long long int)isExistRange0_255_2_2[i * 64 + j] << j);
            //     n3 += ((unsigned long long int)isExistRange0_255_3_3[i * 64 + j] << j);
            //     n4 += ((unsigned long long int)isExistRange0_255_4_4[i * 64 + j] << j);
            //     n5 += ((unsigned long long int)isExistRange0_255_5_5[i * 64 + j] << j);
            //     n6 += ((unsigned long long int)isExistRange0_255_6_6[i * 64 + j] << j);
            //     n7 += ((unsigned long long int)isExistRange0_255_7_7[i * 64 + j] << j);
            //     n8 += ((unsigned long long int)isExistRange0_255_8_8[i * 64 + j] << j);
            // }
            // ptr1[i] = n1;
            // ptr2[i] = n2;
            // ptr3[i] = n3;
            // ptr4[i] = n4;
            // ptr5[i] = n5;
            // ptr6[i] = n6;
            // ptr7[i] = n7;
            // ptr8[i] = n8;
        }
        auto time_cycle3_start = std::chrono::system_clock::now();
        auto cycle3 = getcycle();

        // alignas(64) unsigned char isExistRange0_255_4bit_16[16 * 16] = {0};//1 for exist , 0 for not exist
        // alignas(64) unsigned char stroageEncounterNum_4bit_16[16 * 16] = {0};//存储出现过的num(range:0-15)
        // alignas(64) unsigned char EncounterNum_to_EncodeNum_4bit_16[16 * 16] = {0};//存储出现过的num压缩时的序号。
        unsigned char count4bit_16[16] = {0};
        unsigned long long int ans[16] = {0};
        unsigned long long int ans2[16] = {0};
        unsigned long long int offset_decode = 0;
        unsigned char index1[16] = {0}, count_index1 = 0;
        unsigned char index2[16] = {0}, count_index2 = 0;
        unsigned char index3[16] = {0}, count_index3 = 0;

        // for(int i=0;i<16;++i){
        //     if(isExistRange0_15[i] & (isExistRange0_15[i]-1) == 0){
        //         offset_decode += int(log2(isExistRange0_15[i])) << (i*4);
        //         //not encode 0bit
        //         index1[count_index1++]=i;
        //     }
        //     else if(isExistRange0_15[i]==65535){
        //         //not encode 4bit
        //         index2[count_index2++]=i;
        //     }
        //     else{
        //         //encode
        //         index3[count_index3++]=i;
        //     }
        // }

        for (int i = 0; i < 16; ++i)
        {
            unsigned char c = 0;
            // unsigned char *ptr = (unsigned char *)(&isExistRange0_15[i]);
            //  unsigned char not1_num1 = count_char_1_sum[ptr[0]];
            //  for(int j=0;j<not1_num1;++j){
            //      stroageEncounterNum_4bit_16[i][j]=char_1_index[ptr[0]][j];
            //  }
            //  unsigned char not1_num2 = count_char_1_sum[ptr[1]];
            //  for(int j=not1_num1;j<(not1_num1+not1_num2);++j){
            //      stroageEncounterNum_4bit_16[i][j]=char_1_index[ptr[1]][j-not1_num1]+8;
            //  }
            //  c=(not1_num1+not1_num2);

            // __builtin_prefetch(&char_1_index[ptr[0]][0]);
            // for(int j=0;j<2;++j){
            //     unsigned char not1_num = count_char_1_sum[ ptr[j] ];
            //     unsigned char offset = 8*j;
            //     for(unsigned char k=0;k<not1_num;++k){
            //         //stroageEncounterNum5_0[count5_0 + j] = char_1_index[num0][j] + offset;
            //         //EncounterNum_to_EncodeNum5_0[stroageEncounterNum5_0[count5_0 + j]] = count5_0 + j;
            //         //stroageEncounterNum_4bit_16[i][c+k]=char_1_index[ ptr[j] ][k]+offset;
            //         EncounterNum_to_EncodeNum_4bit_16[i][ stroageEncounterNum_4bit_16[i][c+k]=char_1_index[ ptr[j] ][k]+offset ]=c+k;
            //     }
            //     c+=not1_num;
            // }
            // if(i<15)__builtin_prefetch(&char_1_index[isExistRange0_15[i+1]][0]);
            // if(i<15)__builtin_prefetch(&count_ushort_1_sum[isExistRange0_15[i+1]]);
            // count4bit_16[i]=count_ushort_1_sum[isExistRange0_15[i]];
            // memcpy();
            // for(int j=0;j<count4bit_16[i];++j){
            //     //stroageEncounterNum_4bit_16[i][j]=ushort_1_index[isExistRange0_15[i]][j];
            //     //EncounterNum_to_EncodeNum_4bit_16[i][stroageEncounterNum_4bit_16[i][j]]=j;
            // }
            // for(int j=0;j<count4bit_16[i];++j){
            //     //EncounterNum_to_EncodeNum_4bit_16[i][stroageEncounterNum_4bit_16[i][j]]=j;
            // }

            // for(int j=0;j<16;++j){
            //     //stroageEncounterNum_4bit_16[i][j]= j *
            // }
            // unsigned long long int *p=(unsigned long long int *)&EncounterNum_to_EncodeNum_4bit_16[i][0];
            unsigned long long int tmp_ans = 0;
            unsigned long long int tmp_ans2 = 0;
            for (unsigned char j = 0; j < 16; ++j)
            {
                // unsigned char tmp = ((isExistRange0_15[i] >> j) & 1); // 0 or 1 可用simd
                // stroageEncounterNum_4bit_16[i][c] = j * tmp;
                // ans[i] |= ((((unsigned long long int)j) << (4 * c)) * tmp);
                // // tmp_ans |= ( (j*tmp)<<(4*c) );
                // EncounterNum_to_EncodeNum_4bit_16[i][j] = c;
                // ans2[i] = (ans2[i] << 4) + c;
                // // tmp_ans2 = (ans2[i] << 4) + c;
                // c += tmp;
                // ans = (ans << 8) + c;
            }
            // ans[i]=tmp_ans;
            // ans2[i]=tmp_ans2;
            //  p[0]=ans;
            //  ans=0;
            //  for(unsigned char j = 8; j < 16; ++j){
            //      unsigned char tmp= ((isExistRange0_15[i]>>j) & 1);//0 or 1
            //      stroageEncounterNum_4bit_16[i][c] = j * tmp;
            //      //EncounterNum_to_EncodeNum_4bit_16[i][j] = c;
            //      c += tmp;
            //      ans = (ans << 8) + c;
            //  }
            //  p[1]=ans;

            for (unsigned char j = 0; j < c; ++j)
            {
                // EncounterNum_to_EncodeNum_4bit_16[i][ stroageEncounterNum_4bit_16[i][j] ] = j;
            }
            // count4bit_16[i] = c;
            //  stroageEncounterNum5_0[count5_0]= (i) * ((num5_0 >> i) & 1);
            //  count5_0 += ((num5_0 >> i) & 1);
        }

        for (int i = 0; i < 16; ++i)
        {
            for (int j = 0; j < count4bit_16[i]; ++j)
            {
                // EncounterNum_to_EncodeNum_4bit_16[i][stroageEncounterNum_4bit_16[i][j]] = j;
            }
        }
        // for (int i = 0; i < count1; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_1[stroageEncounterNum_1[i]] = i;
        //     }

        // _mm256_storeu_epi64(isExistRange0_255_1,m256_1);
        // _mm256_storeu_epi64(isExistRange0_255_2,m256_2);
        // _mm256_storeu_epi64(isExistRange0_255_3,m256_3);
        // _mm256_storeu_epi64(isExistRange0_255_4,m256_4);
        // _mm256_storeu_epi64(isExistRange0_255_5,m256_5);
        // _mm256_storeu_epi64(isExistRange0_255_6,m256_6);
        // _mm256_storeu_epi64(isExistRange0_255_7,m256_7);
        // _mm256_storeu_epi64(isExistRange0_255_8,m256_8);

        // _mm512_store_si512((void *)isExistRange0_255_12, m512_12);
        // _mm512_store_si512((void *)isExistRange0_255_34, m512_34);
        // _mm512_store_si512((void *)isExistRange0_255_56, m512_56);
        // _mm512_store_si512((void *)isExistRange0_255_78, m512_78);
        // memcpy(isExistRange0_255_2, &isExistRange0_255_12[0], 32);
        // memcpy(isExistRange0_255_1, &isExistRange0_255_12[32], 32);
        // memcpy(isExistRange0_255_4, &isExistRange0_255_34[0], 32);
        // memcpy(isExistRange0_255_3, &isExistRange0_255_34[32], 32);
        // memcpy(isExistRange0_255_6, &isExistRange0_255_56[0], 32);
        // memcpy(isExistRange0_255_5, &isExistRange0_255_56[32], 32);
        // memcpy(isExistRange0_255_8, &isExistRange0_255_78[0], 32);
        // memcpy(isExistRange0_255_7, &isExistRange0_255_78[32], 32);

        int sum = 0, all_bit = 0, min_bit = 0;
        // int sum_[8]={0};
        int sum1 = 0;
        int sum2 = 0;
        int sum3 = 0;
        int sum4 = 0;
        int sum5 = 0;
        int sum6 = 0;
        int sum7 = 0;
        int sum8 = 0;
        int sum_of_2_to_127 = 0;

        alignas(64) unsigned char stroageEncounterNum_01234567891011rest4[12 * 32 + 16] = {0};
        unsigned char *const stroageEncounterNum5_0 = &stroageEncounterNum_01234567891011rest4[0 * 32];      //
        unsigned char *const stroageEncounterNum5_1 = &stroageEncounterNum_01234567891011rest4[1 * 32];      //
        unsigned char *const stroageEncounterNum5_2 = &stroageEncounterNum_01234567891011rest4[2 * 32];      //
        unsigned char *const stroageEncounterNum5_3 = &stroageEncounterNum_01234567891011rest4[3 * 32];      //
        unsigned char *const stroageEncounterNum5_4 = &stroageEncounterNum_01234567891011rest4[4 * 32];      //
        unsigned char *const stroageEncounterNum5_5 = &stroageEncounterNum_01234567891011rest4[5 * 32];      //
        unsigned char *const stroageEncounterNum5_6 = &stroageEncounterNum_01234567891011rest4[6 * 32];      //
        unsigned char *const stroageEncounterNum5_7 = &stroageEncounterNum_01234567891011rest4[7 * 32];      //
        unsigned char *const stroageEncounterNum5_8 = &stroageEncounterNum_01234567891011rest4[8 * 32];      //
        unsigned char *const stroageEncounterNum5_9 = &stroageEncounterNum_01234567891011rest4[9 * 32];      //
        unsigned char *const stroageEncounterNum5_10 = &stroageEncounterNum_01234567891011rest4[10 * 32];    //
        unsigned char *const stroageEncounterNum5_11 = &stroageEncounterNum_01234567891011rest4[11 * 32];    //
        unsigned char *const stroageEncounterNum5_rest4 = &stroageEncounterNum_01234567891011rest4[12 * 32]; //
        alignas(64) unsigned char EncounterNum_to_EncodeNum_01234567891011rest4[12 * 32 + 16] = {0};         //
        unsigned char *const EncounterNum_to_EncodeNum5_0 = &EncounterNum_to_EncodeNum_01234567891011rest4[0 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_1 = &EncounterNum_to_EncodeNum_01234567891011rest4[1 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_2 = &EncounterNum_to_EncodeNum_01234567891011rest4[2 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_3 = &EncounterNum_to_EncodeNum_01234567891011rest4[3 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_4 = &EncounterNum_to_EncodeNum_01234567891011rest4[4 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_5 = &EncounterNum_to_EncodeNum_01234567891011rest4[5 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_6 = &EncounterNum_to_EncodeNum_01234567891011rest4[6 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_7 = &EncounterNum_to_EncodeNum_01234567891011rest4[7 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_8 = &EncounterNum_to_EncodeNum_01234567891011rest4[8 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_9 = &EncounterNum_to_EncodeNum_01234567891011rest4[9 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_10 = &EncounterNum_to_EncodeNum_01234567891011rest4[10 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_11 = &EncounterNum_to_EncodeNum_01234567891011rest4[11 * 32];
        unsigned char *const EncounterNum_to_EncodeNum5_rest4 = &EncounterNum_to_EncodeNum_01234567891011rest4[12 * 32];
        int count5_0 = 0, count5_1 = 0, count5_2 = 0, count5_3 = 0, count5_4 = 0, count5_5 = 0, count5_6 = 0,
            count5_7 = 0, count5_8 = 0, count5_9 = 0, count5_10 = 0, count5_11 = 0, count5_rest4 = 0;

        // for (unsigned char ii = 0; ii < 4; ++ii)
        // {
        //     unsigned char offset = (unsigned char)(8) * ii;

        //     unsigned char num0 = ((num5_0 >> (ii*8)) & 0xff);
        //     unsigned char not1_num0 = count_char_1_sum[num0];
        //     unsigned char num1 = ((num5_1 >> (ii*8)) & 0xff);
        //     unsigned char not1_num1 = count_char_1_sum[num1];
        //     unsigned char num2 = ((num5_2 >> (ii*8)) & 0xff);
        //     unsigned char not1_num2 = count_char_1_sum[num2];
        //     unsigned char num3 = ((num5_3 >> (ii*8)) & 0xff);
        //     unsigned char not1_num3 = count_char_1_sum[num3];
        //     unsigned char num4 = ((num5_4 >> (ii*8)) & 0xff);
        //     unsigned char not1_num4 = count_char_1_sum[num4];
        //     unsigned char num5 = ((num5_5 >> (ii*8)) & 0xff);
        //     unsigned char not1_num5 = count_char_1_sum[num5];
        //     unsigned char num6 = ((num5_6 >> (ii*8)) & 0xff);
        //     unsigned char not1_num6 = count_char_1_sum[num6];
        //     unsigned char num7 = ((num5_7 >> (ii*8)) & 0xff);
        //     unsigned char not1_num7 = count_char_1_sum[num7];
        //     unsigned char num8 = ((num5_8 >> (ii*8)) & 0xff);
        //     unsigned char not1_num8 = count_char_1_sum[num8];
        //     unsigned char num9 = ((num5_9 >> (ii*8)) & 0xff);
        //     unsigned char not1_num9 = count_char_1_sum[num9];
        //     unsigned char num10 = ((num5_10 >> (ii*8)) & 0xff);
        //     unsigned char not1_num10 = count_char_1_sum[num10];
        //     unsigned char num11 = ((num5_11 >> (ii*8)) & 0xff);
        //     unsigned char not1_num11 = count_char_1_sum[num11];
        //     //unsigned char numrest4 = ((num5_rest4 >> (ii*4)) & 0xff);
        //     //unsigned char not1_numrest4 = count_char_1_sum[numrest4];

        //     for (unsigned char j = 0; j < not1_num0; ++j)
        //     {
        //         stroageEncounterNum5_0[count5_0 + j] = char_1_index[num0][j] + offset;
        //         EncounterNum_to_EncodeNum5_0[stroageEncounterNum5_0[count5_0 + j]] = count5_0 + j;
        //     }
        //     count5_0 += not1_num0;
        //     for (unsigned char j = 0; j < not1_num1; ++j)
        //     {
        //         stroageEncounterNum5_1[count5_1 + j] = char_1_index[num1][j] + offset;
        //         EncounterNum_to_EncodeNum5_1[stroageEncounterNum5_1[count5_1 + j]] = count5_1 + j;
        //     }
        //     count5_1 += not1_num1;
        //     for (unsigned char j = 0; j < not1_num2; ++j)
        //     {
        //         stroageEncounterNum5_2[count5_2 + j] = char_1_index[num2][j] + offset;
        //         EncounterNum_to_EncodeNum5_2[stroageEncounterNum5_2[count5_2 + j]] = count5_2 + j;
        //     }
        //     count5_2 += not1_num2;
        //     for (unsigned char j = 0; j < not1_num3; ++j)
        //     {
        //         stroageEncounterNum5_3[count5_3 + j] = char_1_index[num3][j] + offset;
        //         EncounterNum_to_EncodeNum5_3[stroageEncounterNum5_3[count5_3 + j]] = count5_3 + j;
        //     }
        //     count5_3 += not1_num3;
        //     for (unsigned char j = 0; j < not1_num4; ++j)
        //     {
        //         stroageEncounterNum5_4[count5_4 + j] = char_1_index[num4][j] + offset;
        //         EncounterNum_to_EncodeNum5_4[stroageEncounterNum5_4[count5_4 + j]] = count5_4 + j;
        //     }
        //     count5_4 += not1_num4;
        //     for (unsigned char j = 0; j < not1_num5; ++j)
        //     {
        //         stroageEncounterNum5_5[count5_5 + j] = char_1_index[num5][j] + offset;
        //         EncounterNum_to_EncodeNum5_5[stroageEncounterNum5_5[count5_5 + j]] = count5_5 + j;
        //     }
        //     count5_5 += not1_num5;
        //     for (unsigned char j = 0; j < not1_num6; ++j)
        //     {
        //         stroageEncounterNum5_6[count5_6 + j] = char_1_index[num6][j] + offset;
        //         EncounterNum_to_EncodeNum5_6[stroageEncounterNum5_6[count5_6 + j]] = count5_6 + j;
        //     }
        //     count5_6 += not1_num6;
        //     for (unsigned char j = 0; j < not1_num7; ++j)
        //     {
        //         stroageEncounterNum5_7[count5_7 + j] = char_1_index[num7][j] + offset;
        //         EncounterNum_to_EncodeNum5_7[stroageEncounterNum5_7[count5_7 + j]] = count5_7 + j;
        //     }
        //     count5_7 += not1_num7;
        //     for (unsigned char j = 0; j < not1_num8; ++j)
        //     {
        //         stroageEncounterNum5_8[count5_8 + j] = char_1_index[num8][j] + offset;
        //         EncounterNum_to_EncodeNum5_8[stroageEncounterNum5_8[count5_8 + j]] = count5_8 + j;
        //     }
        //     count5_8 += not1_num8;
        //     for (unsigned char j = 0; j < not1_num9; ++j)
        //     {
        //         stroageEncounterNum5_9[count5_9 + j] = char_1_index[num9][j] + offset;
        //         EncounterNum_to_EncodeNum5_9[stroageEncounterNum5_9[count5_9 + j]] = count5_9 + j;
        //     }
        //     count5_9 += not1_num9;
        //     for (unsigned char j = 0; j < not1_num10; ++j)
        //     {
        //         stroageEncounterNum5_10[count5_10 + j] = char_1_index[num10][j] + offset;
        //         EncounterNum_to_EncodeNum5_10[stroageEncounterNum5_10[count5_10 + j]] = count5_10 + j;
        //     }
        //     count5_10 += not1_num10;
        //     for (unsigned char j = 0; j < not1_num11; ++j)
        //     {
        //         stroageEncounterNum5_11[count5_11 + j] = char_1_index[num11][j] + offset;
        //         EncounterNum_to_EncodeNum5_11[stroageEncounterNum5_11[count5_11 + j]] = count5_11 + j;
        //     }
        //     count5_11 += not1_num11;
        // }
        // for (unsigned char ii = 0; ii < 2; ++ii){
        //     unsigned char offset = (unsigned char)(8) * ii;
        //     unsigned char numrest4 = ((num5_rest4 >> (ii*8)) & 0xff);
        //     unsigned char not1_numrest4 = count_char_1_sum[numrest4];
        //     for (unsigned char j = 0; j < not1_numrest4; ++j)
        //     {
        //         stroageEncounterNum5_rest4[count5_rest4 + j] = char_1_index[numrest4][j] + offset;
        //         EncounterNum_to_EncodeNum5_rest4[stroageEncounterNum5_rest4[count5_rest4 + j]] = count5_rest4 + j;
        //     }
        //     count5_rest4 += not1_numrest4;
        // }
        for (int i = 0; i < 32; ++i)
        {
            // stroageEncounterNum5_0[count5_0]= (i) * ((num5_0 >> i) & 1);
            // count5_0 += ((num5_0 >> i) & 1);
            // stroageEncounterNum5_1[count5_1]= (i) * ((num5_1 >> i) & 1);
            // count5_1 += ((num5_1 >> i) & 1);
            // stroageEncounterNum5_2[count5_2]= (i) * ((num5_2 >> i) & 1);
            // count5_2 += ((num5_2 >> i) & 1);
            // stroageEncounterNum5_3[count5_3]= (i) * ((num5_3 >> i) & 1);
            // count5_3 += ((num5_3 >> i) & 1);
            // stroageEncounterNum5_4[count5_4]= (i) * ((num5_4 >> i) & 1);
            // count5_4 += ((num5_4 >> i) & 1);
            // stroageEncounterNum5_5[count5_5]= (i) * ((num5_5 >> i) & 1);
            // count5_5 += ((num5_5 >> i) & 1);
            // stroageEncounterNum5_6[count5_6]= (i) * ((num5_6 >> i) & 1);
            // count5_6 += ((num5_6 >> i) & 1);
            // stroageEncounterNum5_7[count5_7]= (i) * ((num5_7 >> i) & 1);
            // count5_7 += ((num5_7 >> i) & 1);
            // stroageEncounterNum5_8[count5_8]= (i) * ((num5_8 >> i) & 1);
            // count5_8 += ((num5_8 >> i) & 1);
            // stroageEncounterNum5_9[count5_9]= (i) * ((num5_9 >> i) & 1);
            // count5_9 += ((num5_9 >> i) & 1);
            // stroageEncounterNum5_10[count5_10]= (i) * ((num5_10 >> i) & 1);
            // count5_10 += ((num5_10 >> i) & 1);
            // stroageEncounterNum5_11[count5_11]= (i) * ((num5_11 >> i) & 1);
            // count5_11 += ((num5_11 >> i) & 1);
        }
        for (int i = 0; i < 16; ++i)
        {
            // stroageEncounterNum5_rest4[count5_rest4]= (i) * ((num5_rest4 >> i) & 1);
            // count5_rest4 += ((num5_rest4 >> i) & 1);
        }
        // printf("count5_0=%d\n",count5_0);
        // printf("count5_1=%d\n",count5_1);
        // printf("count5_2=%d\n",count5_2);
        // printf("count5_3=%d\n",count5_3);
        // printf("count5_4=%d\n",count5_4);
        // printf("count5_5=%d\n",count5_5);
        // printf("count5_6=%d\n",count5_6);
        // printf("count5_7=%d\n",count5_7);
        // printf("count5_8=%d\n",count5_8);
        // printf("count5_9=%d\n",count5_9);
        // printf("count5_10=%d\n",count5_10);
        // printf("count5_11=%d\n",count5_11);
        // printf("count5_rest4=%d\n",count5_rest4);

        // for (int i = 0; i < count5_0; ++i){EncounterNum_to_EncodeNum5_0[stroageEncounterNum5_0[i]] = i;}
        // for (int i = 0; i < count5_1; ++i){EncounterNum_to_EncodeNum5_1[stroageEncounterNum5_1[i]] = i;}
        // for (int i = 0; i < count5_2; ++i){EncounterNum_to_EncodeNum5_2[stroageEncounterNum5_2[i]] = i;}
        // for (int i = 0; i < count5_3; ++i){EncounterNum_to_EncodeNum5_3[stroageEncounterNum5_3[i]] = i;}
        // for (int i = 0; i < count5_4; ++i){EncounterNum_to_EncodeNum5_4[stroageEncounterNum5_4[i]] = i;}
        // for (int i = 0; i < count5_5; ++i){EncounterNum_to_EncodeNum5_5[stroageEncounterNum5_5[i]] = i;}
        // for (int i = 0; i < count5_6; ++i){EncounterNum_to_EncodeNum5_6[stroageEncounterNum5_6[i]] = i;}
        // for (int i = 0; i < count5_7; ++i){EncounterNum_to_EncodeNum5_7[stroageEncounterNum5_7[i]] = i;}
        // for (int i = 0; i < count5_8; ++i){EncounterNum_to_EncodeNum5_8[stroageEncounterNum5_8[i]] = i;}
        // for (int i = 0; i < count5_9; ++i){EncounterNum_to_EncodeNum5_9[stroageEncounterNum5_9[i]] = i;}
        // for (int i = 0; i < count5_10; ++i){EncounterNum_to_EncodeNum5_10[stroageEncounterNum5_10[i]] = i;}
        // for (int i = 0; i < count5_11; ++i){EncounterNum_to_EncodeNum5_11[stroageEncounterNum5_11[i]] = i;}
        // for (int i = 0; i < count5_rest4; ++i){EncounterNum_to_EncodeNum5_rest4[stroageEncounterNum5_rest4[i]] = i;}

        for (int i = 0; i < 32; ++i)
        {
            for (int j = 0; j < 8; ++j)
            {
                // isExistRange0_255_1[ i ] |= (isExistRange0_255_1_1[ i*8+j ] << j);
                // isExistRange0_255_2[ i ] |= (isExistRange0_255_2_2[ i*8+j ] << j);
                // isExistRange0_255_3[i] |= (isExistRange0_255_3_3[i * 8 + j] << j);
                // isExistRange0_255_4[i] |= (isExistRange0_255_4_4[i * 8 + j] << j);
                // isExistRange0_255_5[i] |= (isExistRange0_255_5_5[i * 8 + j] << j);
                // isExistRange0_255_6[i] |= (isExistRange0_255_6_6[i * 8 + j] << j);
                // isExistRange0_255_7[i] |= (isExistRange0_255_7_7[i * 8 + j] << j);
                // isExistRange0_255_8[i] |= (isExistRange0_255_8_8[i * 8 + j] << j);
            }
        }
        for (int i = 0; i < 4; ++i)
        {
            // unsigned long long int n1 = 0;
            // unsigned long long int n2 = 0;
            // unsigned long long int n3 = 0;
            // unsigned long long int n4 = 0;
            // unsigned long long int n5 = 0;
            // unsigned long long int n6 = 0;
            // unsigned long long int n7 = 0;
            // unsigned long long int n8 = 0;
            // for (int j = 0; j < 64; ++j)
            // {
            //     n1 += ((unsigned long long int)isExistRange0_255_1_1[i * 64 + j] << j);
            //     n2 += ((unsigned long long int)isExistRange0_255_2_2[i * 64 + j] << j);
            //     n3 += ((unsigned long long int)isExistRange0_255_3_3[i * 64 + j] << j);
            //     n4 += ((unsigned long long int)isExistRange0_255_4_4[i * 64 + j] << j);
            //     n5 += ((unsigned long long int)isExistRange0_255_5_5[i * 64 + j] << j);
            //     n6 += ((unsigned long long int)isExistRange0_255_6_6[i * 64 + j] << j);
            //     n7 += ((unsigned long long int)isExistRange0_255_7_7[i * 64 + j] << j);
            //     n8 += ((unsigned long long int)isExistRange0_255_8_8[i * 64 + j] << j);
            // }
            // ptr1[i] = n1;
            // ptr2[i] = n2;
            // ptr3[i] = n3;
            // ptr4[i] = n4;
            // ptr5[i] = n5;
            // ptr6[i] = n6;
            // ptr7[i] = n7;
            // ptr8[i] = n8;
        }

        // for (int i = 0; i < 4; ++i)
        // {
        //     sum1 += _popcnt64(ptr1[i]);//0-64     //采用指令集加速
        //     sum2 += _popcnt64(ptr2[i]);
        //     sum3 += _popcnt64(ptr3[i]);
        //     sum4 += _popcnt64(ptr4[i]);
        //     sum5 += _popcnt64(ptr5[i]);
        //     sum6 += _popcnt64(ptr6[i]);
        //     sum7 += _popcnt64(ptr7[i]);
        //     sum8 += _popcnt64(ptr8[i]);
        // }
        int count1 = 0;
        int count2 = 0;
        int count3 = 0;
        int count4 = 0;
        int count5 = 0;
        int count6 = 0;
        int count7 = 0;
        int count8 = 0;

#if 1
        for (int i = 0; i < 32; ++i)
        {
            for (int j = 0; j < 8; ++j)
            {
                // stroageEncounterNum_1[count1] = (i * 8 + j) * ((isExistRange0_255_1[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_1[stroageEncounterNum_1[count1]] =  (i * 8 + j);
                // count1 += ((isExistRange0_255_1[i] >> j) & 1);

                // stroageEncounterNum_2[count2] = (i * 8 + j) * ((isExistRange0_255_2[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_2[stroageEncounterNum_2[count2]] =  (i * 8 + j);
                // count2 += ((isExistRange0_255_2[i] >> j) & 1);

                // stroageEncounterNum_3[count3] = (i * 8 + j) * ((isExistRange0_255_3[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_3[stroageEncounterNum_3[count3]] =  (i * 8 + j);
                // count3 += ((isExistRange0_255_3[i] >> j) & 1);

                // stroageEncounterNum_4[count4] = (i * 8 + j) * ((isExistRange0_255_4[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_4[stroageEncounterNum_4[count4]] =  (i * 8 + j);
                // count4 += ((isExistRange0_255_4[i] >> j) & 1);

                // stroageEncounterNum_5[count5] = (i * 8 + j) * ((isExistRange0_255_5[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_5[stroageEncounterNum_5[count5]] =  (i * 8 + j);
                // count5 += ((isExistRange0_255_5[i] >> j) & 1);

                // stroageEncounterNum_6[count6] = (i * 8 + j) * ((isExistRange0_255_6[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_6[stroageEncounterNum_6[count6]] =  (i * 8 + j);
                // count6 += ((isExistRange0_255_6[i] >> j) & 1);

                // stroageEncounterNum_7[count7] = (i * 8 + j) * ((isExistRange0_255_7[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_7[stroageEncounterNum_7[count7]] =  (i * 8 + j);
                // count7 += ((isExistRange0_255_7[i] >> j) & 1);

                // stroageEncounterNum_8[count8] = (i * 8 + j) * ((isExistRange0_255_8[i] >> j) & 1);
                // // EncounterNum_to_EncodeNum_8[stroageEncounterNum_8[count8]] =  (i * 8 + j);
                // count8 += ((isExistRange0_255_8[i] >> j) & 1);
            }
        }
        for (int i = 0; i < 4; ++i)
        {
            // sum1 += _popcnt64(ptr1[i]);//0-64     //采用指令集加速
            // sum2 += _popcnt64(ptr2[i]);
            // sum3 += _popcnt64(ptr3[i]);
            // sum4 += _popcnt64(ptr4[i]);
            // sum5 += _popcnt64(ptr5[i]);
            // sum6 += _popcnt64(ptr6[i]);
            // sum7 += _popcnt64(ptr7[i]);
            // sum8 += _popcnt64(ptr8[i]);
        }
        for (int i = 0; i < 256; ++i)
        {
            // stroageEncounterNum_1[count1] = (isExistRange0_255_1_1[i] & 1) * i;
            // count1 += (isExistRange0_255_1_1[i] & 1);

            // stroageEncounterNum_2[count2] = (isExistRange0_255_2_2[i] & 1) * i;
            // count2 += (isExistRange0_255_2_2[i] & 1);

            // stroageEncounterNum_3[count3] = (isExistRange0_255_3_3[i] & 1) * i;
            // count3 += (isExistRange0_255_3_3[i] & 1);

            // stroageEncounterNum_4[count4] = (isExistRange0_255_4_4[i] & 1) * i;
            // count4 += (isExistRange0_255_4_4[i] & 1);

            // stroageEncounterNum_5[count5] = (isExistRange0_255_5_5[i] & 1) * i;
            // count5 += (isExistRange0_255_5_5[i] & 1);

            // stroageEncounterNum_6[count6] = (isExistRange0_255_6_6[i] & 1) * i;
            // count6 += (isExistRange0_255_6_6[i] & 1);

            // stroageEncounterNum_7[count7] = (isExistRange0_255_7_7[i] & 1) * i;
            // count7 += (isExistRange0_255_7_7[i] & 1);

            // stroageEncounterNum_8[count8] = (isExistRange0_255_8_8[i] & 1) * i;
            // count8 += (isExistRange0_255_8_8[i] & 1);
        }

        // //if (count1 != 256)
        //     for (int i = 0; i < count1; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_1[stroageEncounterNum_1[i]] = i;
        //     }
        // //if (count2 != 256)
        //     for (int i = 0; i < count2; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_2[stroageEncounterNum_2[i]] = i;
        //     }
        // //if (count3 != 256)
        //     for (int i = 0; i < count3; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_3[stroageEncounterNum_3[i]] = i;
        //     }
        // //if (count4 != 256)
        //     for (int i = 0; i < count4; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_4[stroageEncounterNum_4[i]] = i;
        //     }
        // //if (count5 != 256)
        //     for (int i = 0; i < count5; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_5[stroageEncounterNum_5[i]] = i;
        //     }
        // //if (count6 != 256)
        //     for (int i = 0; i < count6; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_6[stroageEncounterNum_6[i]] = i;
        //     }
        // //if (count7 != 256)
        //     for (int i = 0; i < count7; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_7[stroageEncounterNum_7[i]] = i;
        //     }
        // //if (count8 != 256)
        //     for (int i = 0; i < count8; ++i)
        //     {
        //         EncounterNum_to_EncodeNum_8[stroageEncounterNum_8[i]] = i;
        //     }
#else
        //__builtin_prefetch (const void *addr[, rw[, locality]]);
        __builtin_prefetch(char_1_index);
        __builtin_prefetch(count_char_1_sum);
        for (int i = 0; i < 32; ++i)
        {
            // 1
            // int not1_num_1 = (count_char_1_sum[isExistRange0_255_1[i] / 2] >> (isExistRange0_255_1[i] & 1) * 4) & 0xf;
            int not1_num_1 = count_char_1_sum[isExistRange0_255_1[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_1; ++j)
            {
                stroageEncounterNum_1[count1 + j] = char_1_index[isExistRange0_255_1[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_1[stroageEncounterNum_1[count1 + j]] = count1 + j;
            }
            count1 += not1_num_1;
            // 2
            // int not1_num_2 = (count_char_1_sum[isExistRange0_255_2[i] / 2] >> (isExistRange0_255_2[i] & 1) * 4) & 0xf;
            int not1_num_2 = count_char_1_sum[isExistRange0_255_2[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_2; ++j)
            {
                stroageEncounterNum_2[count2 + j] = char_1_index[isExistRange0_255_2[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_2[stroageEncounterNum_2[count2 + j]] = count2 + j;
            }
            count2 += not1_num_2;
            // 3
            // int not1_num_3 = (count_char_1_sum[isExistRange0_255_3[i] / 2] >> (isExistRange0_255_3[i] & 1) * 4) & 0xf;
            int not1_num_3 = count_char_1_sum[isExistRange0_255_3[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_3; ++j)
            {
                stroageEncounterNum_3[count3 + j] = char_1_index[isExistRange0_255_3[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_3[stroageEncounterNum_3[count3 + j]] = count3 + j;
            }
            count3 += not1_num_3;
            // 4
            // int not1_num_4 = (count_char_1_sum[isExistRange0_255_4[i] / 2] >> (isExistRange0_255_4[i] & 1) * 4) & 0xf;
            int not1_num_4 = count_char_1_sum[isExistRange0_255_4[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_4; ++j)
            {
                stroageEncounterNum_4[count4 + j] = char_1_index[isExistRange0_255_4[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_4[stroageEncounterNum_4[count4 + j]] = count4 + j;
            }
            count4 += not1_num_4;

            // 5
            // int not1_num_5 = (count_char_1_sum[isExistRange0_255_5[i] / 2] >> (isExistRange0_255_5[i] & 1) * 4) & 0xf;
            int not1_num_5 = count_char_1_sum[isExistRange0_255_5[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_5; ++j)
            {
                stroageEncounterNum_5[count5 + j] = char_1_index[isExistRange0_255_5[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_5[stroageEncounterNum_5[count5 + j]] = count5 + j;
            }
            count5 += not1_num_5;
            // 6
            // int not1_num_6 = (count_char_1_sum[isExistRange0_255_6[i] / 2] >> (isExistRange0_255_6[i] & 1) * 4) & 0xf;
            int not1_num_6 = count_char_1_sum[isExistRange0_255_6[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_6; ++j)
            {
                stroageEncounterNum_6[count6 + j] = char_1_index[isExistRange0_255_6[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_6[stroageEncounterNum_6[count6 + j]] = count6 + j;
            }
            count6 += not1_num_6;
            // 7
            // int not1_num_7 = (count_char_1_sum[isExistRange0_255_7[i] / 2] >> (isExistRange0_255_7[i] & 1) * 4) & 0xf;
            int not1_num_7 = count_char_1_sum[isExistRange0_255_7[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_7; ++j)
            {
                stroageEncounterNum_7[count7 + j] = char_1_index[isExistRange0_255_7[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_7[stroageEncounterNum_7[count7 + j]] = count7 + j;
            }
            count7 += not1_num_7;
            // 8
            // int not1_num_8 = (count_char_1_sum[isExistRange0_255_8[i] / 2] >> (isExistRange0_255_8[i] & 1) * 4) & 0xf;
            int not1_num_8 = count_char_1_sum[isExistRange0_255_8[i]];
            // not1_num 范围== 0->8
            for (int j = 0; j < not1_num_8; ++j)
            {
                stroageEncounterNum_8[count8 + j] = char_1_index[isExistRange0_255_8[i]][j] + 8 * i;
                EncounterNum_to_EncodeNum_8[stroageEncounterNum_8[count8 + j]] = count8 + j;
            }
            count8 += not1_num_8;
        }
#endif
        // sum1 = count1;
        // sum2 = count2;
        // sum3 = count3;
        // sum4 = count4;
        // sum5 = count5;
        // sum6 = count6;
        // sum7 = count7;
        // sum8 = count8;
        // unsigned long long int offset = (sum1 == 1) * stroageEncounterNum_1[0] +
        //                                 (sum2 == 1) * stroageEncounterNum_2[0] +
        //                                 (sum3 == 1) * stroageEncounterNum_3[0] +
        //                                 (sum4 == 1) * stroageEncounterNum_4[0] +
        //                                 (sum5 == 1) * stroageEncounterNum_5[0] +
        //                                 (sum6 == 1) * stroageEncounterNum_6[0] +
        //                                 (sum7 == 1) * stroageEncounterNum_7[0] +
        //                                 (sum8 == 1) * stroageEncounterNum_8[0];

        // 2-127的数
        // int satify_num = 127;
        // sum_of_2_to_127 = (sum1 >= 2 && sum1 <= satify_num) +
        //                   (sum2 >= 2 && sum2 <= satify_num) +
        //                   (sum3 >= 2 && sum3 <= satify_num) +
        //                   (sum4 >= 2 && sum4 <= satify_num) +
        //                   (sum5 >= 2 && sum5 <= satify_num) +
        //                   (sum6 >= 2 && sum6 <= satify_num) +
        //                   (sum7 >= 2 && sum7 <= satify_num) +
        //                   (sum8 >= 2 && sum8 <= satify_num);

        // if(count1+count2+count3+count4+count5+count6+count7+count8 != sum1+sum2+sum3+sum4+sum5+sum6+sum7+sum8 )printf("error\n");
        // else printf("no error\n");

        // encode
        // bool DECODEOK = true;
        int DECODEOK = 0;
        auto cycle4 = getcycle();
        auto time_cycle3_end = std::chrono::system_clock::now();
        unsigned char num7 = stroageEncounterNum_7[0];
        unsigned char num8 = stroageEncounterNum_8[0];
        // auto writeNbit=[](int n){
        //     for (int i = 0; i < n; ++i)
        //     {
        //         //output[i] = 0;
        //     }
        //     switch(n){
        //         case 0:break;
        //         case 1:break;
        //         case 2:break;
        //         case 3:break;
        //     };
        // };

        unsigned long long int encount_to_encode[16];
        unsigned long long int stroageEncounterNum_4bit[16];
        unsigned long long int decode_offset=0;
        __m512i m512_encount_to_encode[16]; // 64*8=512bit
        __m512i m512_stroageEncounterNum_4bit[16];//32个zmm寄存器
        unsigned char count_1_sum[16];
        unsigned char ceillog2_1_sum[16];
        unsigned char mask[16];
        unsigned char ceillog2_1_prefixsum[16] = {0};
        for (int i = 0; i < 16; ++i)
        {
            encount_to_encode[i] = information_vec[isExistRange0_15[i]-1].EncounterNum_to_EncodeNum;
            stroageEncounterNum_4bit[i] = information_vec[isExistRange0_15[i]-1].stroageEncounterNum;

            m512_encount_to_encode[i] = _mm512_set1_epi64(encount_to_encode[i]);
            m512_stroageEncounterNum_4bit[i] = _mm512_set1_epi64(stroageEncounterNum_4bit[i]);

            count_1_sum[i] = information_vec[isExistRange0_15[i]-1].count_1_sum;
            decode_offset += (count_1_sum[i]==1)*(( ( stroageEncounterNum_4bit[i]) & 15)<< (60-i*4) );
            ceillog2_1_sum[i] = information_vec[isExistRange0_15[i]-1].ceillog2_1_sum;
            mask[i] = 1*((1 << ceillog2_1_sum[i]) - 1);
            if(i>0)ceillog2_1_prefixsum[i] =   ceillog2_1_sum[i-1] + (i > 0 ? ceillog2_1_prefixsum[i - 1] : 0) ;
            if (0)
                printf("isExistRange0_15[%d]=%d,encount_to_encode[%d]=%x,stroageEncounterNum_4bit[%d]=%x,count_1_sum=%d,ceillog2_1_sum=%d,ceillog2_1_prefixsum=%d\n",
                       i, isExistRange0_15[i]-1,
                       i, encount_to_encode[i],
                       i, stroageEncounterNum_4bit[i],
                       information_vec[isExistRange0_15[i]-1].count_1_sum,
                       information_vec[isExistRange0_15[i]-1].ceillog2_1_sum,
                       ceillog2_1_prefixsum[i]);
        }
        __m512i m512_decode_offset = _mm512_set1_epi64(decode_offset);
        for(int i=0;i<16;++i){
            //ceillog2_1_prefixsum[i] = abs(ceillog2_1_prefixsum[i]-4);
        }
        // if (1)
        // #pragma omp parallel for num_threads(8) reduction(+:DECODEOK)

        //__m512i m512=_mm512_loadu_epi64((unsigned long long int*)(input.data()));//读取8个double值
        auto printm512 = [](int j, __m512i m512)
        {
            unsigned long long int res[8];
            _mm512_storeu_epi64(res, m512);
            for (int i = 0; i < 8; ++i)
            {
                printf("j=%d,m512[%d]=%d ", j, i, res[i]);
            }
            printf("\n");
        };
        double res[8] = {0};
        __m512i res_sum = _mm512_set1_epi64(0);
        std::vector<unsigned long long int> compress_result(N);
        // #pragma omp parallel for num_threads(8)

        for (int i = 1; i <= (N/8); ++i)
        {
            V vi;
            V v;
            vi.dou.a = input[i - 1];
            unsigned long long int num = vi.ll.a;

            unsigned char origin[16];
            unsigned char encode4bit_16[16];
            unsigned char decode4bit_16[16];

            __m512i m512_input8double = _mm512_loadu_epi64((unsigned long long int *)(&input[8 * (i - 1)])); // 读取8个double值,当做ull处理
            //__m512i m512_4bit_16[16];
            //__m512i m512_encode_4bit_16[16];
            //__m512i m512_decode_4bit_16[16]; // 16个寄存器
            __m512i m512_encode_result;//= _mm512_set1_epi64(0);
            //__m512i m512_origin[16];
            __m512i m512_decode_result;
            // 共20个zmm寄存器

            // printf("----m512_origin-----\n");
            for (int j = 0; j < 16; ++j)
            {
                // origin[j] = ((num>>(60-j*4))&15);//获取每4bit的值。
                // m512_origin[j] = ((m512 >> (60-j*4)) & 15);
                // printm512(j,m512_origin[j]);
            }
            unsigned long long int encode_ull = 0;

            // printf("----m512_encode-----\n");
            for (int j = 0; j < 16; ++j)
            {
                // encode4bit_16[j] =  ((encount_to_encode[j] >> (4*origin[j])) & 15) ;
                // m512_encode_4bit_16[j] = ((m512_encount_to_encode[j] >> (4 * m512_origin[j])) & 15)   ;
                // unsigned char mask_num = mask[j];
                // m512_encode_result += (((m512_encount_to_encode[j] >> (4 * ((m512_input8double >> (60 - j * 4)) & 15))) & 15) & mask_num ) << ceillog2_1_prefixsum[j];

                // printm512(j,m512_encode_4bit_16[j]);
                // encode4bit_16[j]=EncounterNum_to_EncodeNum_4bit_16[j][(num>>(60-j*4))&15];
                // encode4bit_16[j]= ( >> (((num>>(60-j*4))&15)*4) ) & 15 ;
            }
            // printm512(0,m512_encode_result);

            m512_encode_result =
                ((((m512_encount_to_encode[0] >> (4 * ((m512_input8double >> (60 - 0 * 4)) & 15))) & 15) & mask[0]) << ceillog2_1_prefixsum[0]) +
                ((((m512_encount_to_encode[1] >> (4 * ((m512_input8double >> (60 - 1 * 4)) & 15))) & 15) & mask[1]) << ceillog2_1_prefixsum[1]) +
                ((((m512_encount_to_encode[2] >> (4 * ((m512_input8double >> (60 - 2 * 4)) & 15))) & 15) & mask[2]) << ceillog2_1_prefixsum[2]) +
                ((((m512_encount_to_encode[3] >> (4 * ((m512_input8double >> (60 - 3 * 4)) & 15))) & 15) & mask[3]) << ceillog2_1_prefixsum[3]) +
                ((((m512_encount_to_encode[4] >> (4 * ((m512_input8double >> (60 - 4 * 4)) & 15))) & 15) & mask[4]) << ceillog2_1_prefixsum[4]) +
                ((((m512_encount_to_encode[5] >> (4 * ((m512_input8double >> (60 - 5 * 4)) & 15))) & 15) & mask[5]) << ceillog2_1_prefixsum[5]) +
                ((((m512_encount_to_encode[6] >> (4 * ((m512_input8double >> (60 - 6 * 4)) & 15))) & 15) & mask[6]) << ceillog2_1_prefixsum[6]) +
                ((((m512_encount_to_encode[7] >> (4 * ((m512_input8double >> (60 - 7 * 4)) & 15))) & 15) & mask[7]) << ceillog2_1_prefixsum[7]) +
                ((((m512_encount_to_encode[8] >> (4 * ((m512_input8double >> (60 - 8 * 4)) & 15))) & 15) & mask[8]) << ceillog2_1_prefixsum[8]) +
                ((((m512_encount_to_encode[9] >> (4 * ((m512_input8double >> (60 - 9 * 4)) & 15))) & 15) & mask[9]) << ceillog2_1_prefixsum[9]) +
                ((((m512_encount_to_encode[10] >> (4 * ((m512_input8double >> (60 - 10 * 4)) & 15))) & 15) & mask[10]) << ceillog2_1_prefixsum[10]) +
                ((((m512_encount_to_encode[11] >> (4 * ((m512_input8double >> (60 - 11 * 4)) & 15))) & 15) & mask[11]) << ceillog2_1_prefixsum[11]) +
                ((((m512_encount_to_encode[12] >> (4 * ((m512_input8double >> (60 - 12 * 4)) & 15))) & 15) & mask[12]) << ceillog2_1_prefixsum[12]) +
                ((((m512_encount_to_encode[13] >> (4 * ((m512_input8double >> (60 - 13 * 4)) & 15))) & 15) & mask[13]) << ceillog2_1_prefixsum[13]) +
                ((((m512_encount_to_encode[14] >> (4 * ((m512_input8double >> (60 - 14 * 4)) & 15))) & 15) & mask[14]) << ceillog2_1_prefixsum[14]) +
                ((((m512_encount_to_encode[15] >> (4 * ((m512_input8double >> (60 - 15 * 4)) & 15))) & 15) & mask[15]) << ceillog2_1_prefixsum[15]);

            

            _mm512_storeu_epi64(&compress_result[8*(i-1)],m512_encode_result);


            // printf("----m512_decode-----\n");
            for (int j = 0; j < 16; ++j)
            {
                // decode4bit_16[j] = ((stroageEncounterNum_4bit[j] >> (4*encode4bit_16[j])) & 15) ;
                // m512_decode_4bit_16[j] = (m512_stroageEncounterNum_4bit[j]>>(4*m512_encode_4bit_16[j])) & 15;
                //unsigned char mask_num = mask[j];

                //m512_decode_4bit_16[j] =  ( (m512_stroageEncounterNum_4bit[j] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j]) & mask[j]))) & 15);

                // printm512(j,m512_decode_4bit_16[j]);
                // decode4bit_16[j] = stroageEncounterNum_4bit_16[j][encode4bit_16[j]];
                // decode4bit_16[j] = ans[j] >> (((num>>(60-j*4))&15)*4);
            }
            V decode_result;
            // decode_result.dou.a= input[i-1];

            for (int j = 0; j < 16; ++j)
            {
                // decode_result = (decode_result << 4) + decode4bit_16[j];
            }

            // decode_result.char8.a = (decode4bit_16[0]<<4) + decode4bit_16[1];
            // decode_result.char8.b = (decode4bit_16[2]<<4) + decode4bit_16[3];
            // decode_result.char8.c = (decode4bit_16[4]<<4) + decode4bit_16[5];
            // decode_result.char8.d = (decode4bit_16[6]<<4) + decode4bit_16[7];
            // decode_result.char8.e = (decode4bit_16[8]<<4) + decode4bit_16[9];
            // decode_result.char8.f = (decode4bit_16[10]<<4) + decode4bit_16[11];
            // decode_result.char8.g = (decode4bit_16[12]<<4) + decode4bit_16[13];
            // decode_result.char8.h = (decode4bit_16[14]<<4) + decode4bit_16[15];

            // 解码后的8个double值
            // m512_decode_result =
            //     (m512_decode_4bit_16[0] << (60 - 0 * 4)) + (m512_decode_4bit_16[1] << (60 - 1 * 4)) +
            //     (m512_decode_4bit_16[2] << (60 - 2 * 4)) + (m512_decode_4bit_16[3] << (60 - 3 * 4)) +
            //     (m512_decode_4bit_16[4] << (60 - 4 * 4)) + (m512_decode_4bit_16[5] << (60 - 5 * 4)) +
            //     (m512_decode_4bit_16[6] << (60 - 6 * 4)) + (m512_decode_4bit_16[7] << (60 - 7 * 4)) +
            //     (m512_decode_4bit_16[8] << (60 - 8 * 4)) + (m512_decode_4bit_16[9] << (60 - 9 * 4)) +
            //     (m512_decode_4bit_16[10] << (60 - 10 * 4)) + (m512_decode_4bit_16[11] << (60 - 11 * 4)) +
            //     (m512_decode_4bit_16[12] << (60 - 12 * 4)) + (m512_decode_4bit_16[13] << (60 - 13 * 4)) +
            //     (m512_decode_4bit_16[14] << (60 - 14 * 4)) + (m512_decode_4bit_16[15] << (60 - 15 * 4));

            // m512_decode_result = 
            // (( (m512_stroageEncounterNum_4bit[0] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[0]) & mask[0]))) & 15) << (60-0*4)) + 
            // (( (m512_stroageEncounterNum_4bit[1] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[1]) & mask[1]))) & 15) << (60-1*4)) +  
            // (( (m512_stroageEncounterNum_4bit[2] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[2]) & mask[2]))) & 15) << (60-2*4)) +  
            // (( (m512_stroageEncounterNum_4bit[3] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[3]) & mask[3]))) & 15) << (60-3*4)) +  
            // (( (m512_stroageEncounterNum_4bit[4] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[4]) & mask[4]))) & 15) << (60-4*4)) +  
            // (( (m512_stroageEncounterNum_4bit[5] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[5]) & mask[5]))) & 15) << (60-5*4)) +  
            // (( (m512_stroageEncounterNum_4bit[6] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[6]) & mask[6]))) & 15) << (60-6*4)) +  
            // (( (m512_stroageEncounterNum_4bit[7] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[7]) & mask[7]))) & 15) << (60-7*4)) +  
            // (( (m512_stroageEncounterNum_4bit[8] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[8]) & mask[8]))) & 15) << (60-8*4)) +  
            // (( (m512_stroageEncounterNum_4bit[9] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[9]) & mask[9]))) & 15) << (60-9*4)) +  
            // (( (m512_stroageEncounterNum_4bit[10] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[10]) & mask[10]))) & 15) << (60-10*4)) +  
            // (( (m512_stroageEncounterNum_4bit[11] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[11]) & mask[11]))) & 15) << (60-11*4)) +  
            // (( (m512_stroageEncounterNum_4bit[12] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[12]) & mask[12]))) & 15) << (60-12*4)) +  
            // (( (m512_stroageEncounterNum_4bit[13] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[13]) & mask[13]))) & 15) << (60-13*4)) +  
            // (( (m512_stroageEncounterNum_4bit[14] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[14]) & mask[14]))) & 15) << (60-14*4)) +  
            // (( (m512_stroageEncounterNum_4bit[15] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[15]) & mask[15]))) & 15) << (60-15*4))
            // ;
            

            //res_sum += m512_decode_result;

            //_mm512_storeu_epi64((unsigned long long int*)res,m512_decode_result);

            for (int k = 0; k < 8; ++k)
            {
                //printf("input[%d]=%lf,res[%d]=%lf\n",k,input[k],k,res[k]);
            }

            // double double_decode_result=*(double*)(&decode_result);
            double double_decode_result = decode_result.dou.a;

            // double dnum = input[i - 1];
            //  encode dnum
            // long long int num = *(long long int *)(&dnum);
            //   isExistRange0_255_1[((num >> 56) & 255) / 8] |= (1 << (((num >> 56) & 255) % 8));
            //   isExistRange0_255_2[((num >> 48) & 255) / 8] |= (1 << (((num >> 48) & 255) % 8));
            //   isExistRange0_255_3[((num >> 40) & 255) / 8] |= (1 << (((num >> 40) & 255) % 8));
            //   isExistRange0_255_4[((num >> 32) & 255) / 8] |= (1 << (((num >> 32) & 255) % 8));
            //   isExistRange0_255_5[((num >> 24) & 255) / 8] |= (1 << (((num >> 24) & 255) % 8));
            //   isExistRange0_255_6[((num >> 16) & 255) / 8] |= (1 << (((num >> 16) & 255) % 8));
            //   isExistRange0_255_7[((num >> 8) & 255) / 8] |= (1 << (((num >> 8) & 255) % 8));
            //   isExistRange0_255_8[((num >> 0) & 255) / 8] |= (1 << (((num >> 0) & 255) % 8));
            unsigned char encode1 = EncounterNum_to_EncodeNum_1[vi.char8.a];
            unsigned char encode2 = EncounterNum_to_EncodeNum_2[vi.char8.b];
            unsigned char encode3 = EncounterNum_to_EncodeNum_3[vi.char8.c];
            unsigned char encode4 = EncounterNum_to_EncodeNum_4[vi.char8.d];
            unsigned char encode5 = EncounterNum_to_EncodeNum_5[vi.char8.e];
            unsigned char encode6 = EncounterNum_to_EncodeNum_6[vi.char8.f];
            unsigned char encode7 = EncounterNum_to_EncodeNum_7[vi.char8.g];
            unsigned char encode8 = EncounterNum_to_EncodeNum_8[vi.char8.h];

            const unsigned int tmp = ((1u << 5) - 1); // 0x0001 1111
            // const unsigned int one = 1u;
            // num5_0 |= (one<<( (num >> (64-1*5)) & tmp));//record 5 bit
            // num5_1 |= (one<<( (num >> (64-2*5)) & tmp));
            // num5_2 |= (one<<( (num >> (64-3*5)) & tmp));
            // num5_3 |= (one<<( (num >> (64-4*5)) & tmp));
            // num5_4 |= (one<<( (num >> (64-5*5)) & tmp));
            // num5_5 |= (one<<( (num >> (64-6*5)) & tmp));
            // num5_6 |= (one<<( (num >> (64-7*5)) & tmp));
            // num5_7 |= (one<<( (num >> (64-8*5)) & tmp));
            // num5_8 |= (one<<( (num >> (64-9*5)) & tmp));
            // num5_9 |= (one<<( (num >> (64-10*5)) & tmp));
            // num5_10 |= (one<<( (num >> (64-11*5)) & tmp));
            // num5_11 |= (one<<( (num >> (64-12*5)) & tmp));
            // num5_rest4 |= (one<<( (num >> (0)) & ((1u<<5)-1)));
            unsigned char encode5_0 = EncounterNum_to_EncodeNum5_0[((num >> (64 - 1 * 5)) & tmp)];
            unsigned char encode5_1 = EncounterNum_to_EncodeNum5_1[((num >> (64 - 2 * 5)) & tmp)];
            unsigned char encode5_2 = EncounterNum_to_EncodeNum5_2[((num >> (64 - 3 * 5)) & tmp)];
            unsigned char encode5_3 = EncounterNum_to_EncodeNum5_3[((num >> (64 - 4 * 5)) & tmp)];
            unsigned char encode5_4 = EncounterNum_to_EncodeNum5_4[((num >> (64 - 5 * 5)) & tmp)];
            unsigned char encode5_5 = EncounterNum_to_EncodeNum5_5[((num >> (64 - 6 * 5)) & tmp)];
            unsigned char encode5_6 = EncounterNum_to_EncodeNum5_6[((num >> (64 - 7 * 5)) & tmp)];
            unsigned char encode5_7 = EncounterNum_to_EncodeNum5_7[((num >> (64 - 8 * 5)) & tmp)];
            unsigned char encode5_8 = EncounterNum_to_EncodeNum5_8[((num >> (64 - 9 * 5)) & tmp)];
            unsigned char encode5_9 = EncounterNum_to_EncodeNum5_9[((num >> (64 - 10 * 5)) & tmp)];
            unsigned char encode5_10 = EncounterNum_to_EncodeNum5_10[((num >> (64 - 11 * 5)) & tmp)];
            unsigned char encode5_11 = EncounterNum_to_EncodeNum5_11[((num >> (64 - 12 * 5)) & tmp)];
            unsigned char encode5_rest4 = EncounterNum_to_EncodeNum5_rest4[(num >> (0)) & ((1u << 4) - 1)];

            // decode dnum
            unsigned char decode1 = stroageEncounterNum_1[encode1];
            unsigned char decode2 = stroageEncounterNum_2[encode2];
            unsigned char decode3 = stroageEncounterNum_3[encode3];
            unsigned char decode4 = stroageEncounterNum_4[encode4];
            unsigned char decode5 = stroageEncounterNum_5[encode5];
            unsigned char decode6 = stroageEncounterNum_6[encode6];
            unsigned char decode7 = stroageEncounterNum_7[encode7];
            unsigned char decode8 = stroageEncounterNum_8[encode8];

            // unsigned long long int decode5_0 = stroageEncounterNum5_0[encode5_0];
            // unsigned long long int decode5_1 = stroageEncounterNum5_1[encode5_1];
            // unsigned long long int decode5_2 = stroageEncounterNum5_2[encode5_2];
            // unsigned long long int decode5_3 = stroageEncounterNum5_3[encode5_3];
            // unsigned long long int decode5_4 = stroageEncounterNum5_4[encode5_4];
            // unsigned long long int decode5_5 = stroageEncounterNum5_5[encode5_5];
            // unsigned long long int decode5_6 = stroageEncounterNum5_6[encode5_6];
            // unsigned long long int decode5_7 = stroageEncounterNum5_7[encode5_7];
            // unsigned long long int decode5_8 = stroageEncounterNum5_8[encode5_8];
            // unsigned long long int decode5_9 = stroageEncounterNum5_9[encode5_9];
            // unsigned long long int decode5_10 = stroageEncounterNum5_10[encode5_10];
            // unsigned long long int decode5_11 = stroageEncounterNum5_11[encode5_11];
            // unsigned long long int decode5_rest4 = stroageEncounterNum5_rest4[encode5_rest4];

            unsigned char decode5_0 = stroageEncounterNum5_0[encode5_0];
            unsigned char decode5_1 = stroageEncounterNum5_1[encode5_1];
            unsigned char decode5_2 = stroageEncounterNum5_2[encode5_2];
            unsigned char decode5_3 = stroageEncounterNum5_3[encode5_3];
            unsigned char decode5_4 = stroageEncounterNum5_4[encode5_4];
            unsigned char decode5_5 = stroageEncounterNum5_5[encode5_5];
            unsigned char decode5_6 = stroageEncounterNum5_6[encode5_6];
            unsigned char decode5_7 = stroageEncounterNum5_7[encode5_7];
            unsigned char decode5_8 = stroageEncounterNum5_8[encode5_8];
            unsigned char decode5_9 = stroageEncounterNum5_9[encode5_9];
            unsigned char decode5_10 = stroageEncounterNum5_10[encode5_10];
            unsigned char decode5_11 = stroageEncounterNum5_11[encode5_11];
            unsigned char decode5_rest4 = stroageEncounterNum5_rest4[encode5_rest4];

            // unsigned long long int decode5_value = (decode5_0 << (64-1*5))+
            //                                        (decode5_1 << (64-2*5))+
            //                                        (decode5_2 << (64-3*5))+
            //                                        (decode5_3 << (64-4*5))+
            //                                        (decode5_4 << (64-5*5))+
            //                                        (decode5_5 << (64-6*5))+
            //                                        (decode5_6 << (64-7*5))+
            //                                        (decode5_7 << (64-8*5))+
            //                                        (decode5_8 << (64-9*5))+
            //                                        (decode5_9 << (64-10*5))+
            //                                        (decode5_10 << (64-11*5))+
            //                                        (decode5_11 << (64-12*5))+
            //                                        (decode5_rest4 << 0);

            v.char8.a = decode1;
            v.char8.b = decode2;
            v.char8.c = decode3;
            v.char8.d = decode4;
            v.char8.e = decode5;
            v.char8.f = decode6;
            v.char8.g = decode7;
            v.char8.h = decode8;

            // v.char8.a = (decode5_0 << 3) + ( decode5_1 >> 2);
            // v.char8.b = ((decode5_1 % 4)<<6) + (decode5_2<<1)+ (decode5_3 >> 4);
            // v.char8.c = ((decode5_3 %16)<<4)+(decode5_4>>1);
            // v.char8.d = ((decode5_4 %2)<<7)+(decode5_5<<2)+(decode5_6>>3);
            // v.char8.e = ((decode5_6%8)<<5)+decode5_7;
            // v.char8.f = (decode5_8 << 3) + ( decode5_9 >> 2);;
            // v.char8.g = ((decode5_9 % 4)<<6) + (decode5_10<<1)+ (decode5_11 >> 4);
            // v.char8.h = ((decode5_11 %16)<<4)+(decode5_rest4);

            // v.char8.a = decode1;
            // v.char8.b = decode2;
            // v.char8.c = vi.char8.c;
            // v.char8.d = vi.char8.d;
            // v.char8.e = vi.char8.e;
            // v.char8.f = decode6;
            // v.char8.g = num7;
            // v.char8.h = num8;
            // v.ull.a = (((unsigned long long int)stroageEncounterNum_1[encode1]) << 56) +
            //           (((unsigned long long int)stroageEncounterNum_2[encode2]) << 48) +
            //           (((unsigned long long int)stroageEncounterNum_3[encode3]) << 40) +
            //           (((unsigned long long int)stroageEncounterNum_4[encode4]) << 32) +
            //           (((unsigned long long int)stroageEncounterNum_5[encode5]) << 24) +
            //           (((unsigned long long int)stroageEncounterNum_6[encode6]) << 16) +
            //           (((unsigned long long int)stroageEncounterNum_7[encode7]) << 8) +
            //           (((unsigned long long int)stroageEncounterNum_8[encode8]) << 0);
            // v.ull.a = ((unsigned long long int)stroageEncounterNum_1[encode1]) << 0 +
            //           ((unsigned long long int)stroageEncounterNum_2[encode2]) << 8 +
            //           ((unsigned long long int)stroageEncounterNum_3[encode3]) << 16 +
            //           ((unsigned long long int)stroageEncounterNum_4[encode4]) << 24 +
            //           ((unsigned long long int)stroageEncounterNum_5[encode5]) << 32 +
            //           ((unsigned long long int)stroageEncounterNum_6[encode6]) << 40 +
            //           ((unsigned long long int)stroageEncounterNum_7[encode7]) << 48 +
            //           ((unsigned long long int)stroageEncounterNum_8[encode8]) << 56;

            double decode_num = v.dou.a;
            // double decode_num_2 = *(double*)(&decode5_value);

            // printf("origin=%d,encode1=%d, decode1=%d\n", ((num >> 56) & 255), encode1, decode1);
            // printf("origin=%d,encode2=%d, decode2=%d\n", ((num >> 48) & 255), encode2, decode2);
            // printf("origin=%d,encode3=%d, decode3=%d\n", ((num >> 40) & 255), encode3, decode3);
            // printf("origin=%d,encode4=%d, decode4=%d\n", ((num >> 32) & 255), encode4, decode4);
            // printf("origin=%d,encode5=%d, decode5=%d\n", ((num >> 24) & 255), encode5, decode5);
            // printf("origin=%d,encode6=%d, decode6=%d\n", ((num >> 16) & 255), encode6, decode6);
            // printf("origin=%d,encode7=%d, decode7=%d\n", ((num >> 8) & 255), encode7, decode7);
            // printf("origin=%d,encode8=%d, decode8=%d\n", ((num >> 0) & 255), encode8, decode8);
            // printf("decode_num=%lf\n",decode_num);
            // printf("===================\n");
            // printf("origin0=%d, encode5_0=%d, decode5_0=%d\n",((num >> (64-1*5)) & tmp),encode5_0,decode5_0);
            // printf("origin1=%d, encode5_1=%d, decode5_1=%d\n",((num >> (64-2*5)) & tmp),encode5_1,decode5_1);
            // printf("origin2=%d, encode5_2=%d, decode5_2=%d\n",((num >> (64-3*5)) & tmp),encode5_2,decode5_2);
            // printf("origin3=%d, encode5_3=%d, decode5_3=%d\n",((num >> (64-4*5)) & tmp),encode5_3,decode5_3);
            // printf("origin4=%d, encode5_4=%d, decode5_4=%d\n",((num >> (64-5*5)) & tmp),encode5_4,decode5_4);
            // printf("origin5=%d, encode5_5=%d, decode5_5=%d\n",((num >> (64-6*5)) & tmp),encode5_5,decode5_5);
            // printf("origin6=%d, encode5_6=%d, decode5_6=%d\n",((num >> (64-7*5)) & tmp),encode5_6,decode5_6);
            // printf("origin7=%d, encode5_7=%d, decode5_7=%d\n",((num >> (64-8*5)) & tmp),encode5_7,decode5_7);
            // printf("origin8=%d, encode5_8=%d, decode5_8=%d\n",((num >> (64-9*5)) & tmp),encode5_8,decode5_8);
            // printf("origin9=%d, encode5_9=%d, decode5_9=%d\n",((num >> (64-10*5)) & tmp),encode5_9,decode5_9);
            // printf("origin10=%d, encode5_10=%d, decode5_10=%d\n",((num >> (64-11*5)) & tmp),encode5_10,decode5_10);
            // printf("origin11=%d, encode5_11=%d, decode5_11=%d\n",((num >> (64-12*5)) & tmp),encode5_11,decode5_11);
            // printf("originrest4=%d, encode5_rest4=%d, decode5_rest4=%d\n",((num >> (0)) & ((1u<<4)-1)),encode5_rest4,decode5_rest4);

            for (int k = 0; k < 16; ++k)
            {
                // printf("origin[%d]=%d,encode4bit_16[%d]=%d,decode_4bit_16[%d]=%d\n",k,origin[k],k,encode4bit_16[k],k,decode4bit_16[k]);
            }

            // DECODEOK |= (double_decode_result == vi.dou.a);
            //  DECODEOK= (((num >> (64-1*5)) & tmp) == decode5_0 &&
            //       ((num >> (64-2*5)) & tmp) == decode5_1 &&
            //       ((num >> (64-3*5)) & tmp) == decode5_2 &&
            //       ((num >> (64-4*5)) & tmp) == decode5_3 &&
            //       ((num >> (64-5*5)) & tmp) == decode5_4 &&
            //       ((num >> (64-6*5)) & tmp) == decode5_5 &&
            //       ((num >> (64-7*5)) & tmp) == decode5_6 &&
            //       ((num >> (64-8*5)) & tmp) == decode5_7 &&
            //       ((num >> (64-9*5)) & tmp) == decode5_8 &&
            //       ((num >> (64-10*5)) & tmp) == decode5_9 &&
            //       ((num >> (64-11*5)) & tmp) == decode5_10 &&
            //       ((num >> (64-12*5)) & tmp) == decode5_11 &&
            //       ((num >> (0)) & ((1u<<4)-1)) == decode5_rest4);
            //   DECODEOK += (((num >> (64-1*5)) & tmp) == decode5_0 &&
            //               ((num >> (64-2*5)) & tmp) == decode5_1 );

            // if (decode_num != vi.dou.a)
            {
                // printf("i=%d,error  decode_num=%lf, orgin_num=%lf\n", i,decode_num,vi.dou.a);
                // DECODEOK = 0;
                // break;
            }
        }
        auto time_encode_end = std::chrono::system_clock::now();
        printf("start decode\n");
        auto cycle5 = getcycle();

        int cmp_res[8];
        for(int i=0;i<16;i+=2){
            // if( count_1_sum[i]==1 && count_1_sum[i+1]==1 )cmp_res[i/2]=1;
            // else if( count_1_sum[i]==1 && 2<=count_1_sum[i+1] && count_1_sum[i+1]<=15 )cmp_res[i/2]=2;
            // else if( count_1_sum[i]==1 && count_1_sum[i+1]==16 )cmp_res[i/2]=3;
            // else if( 2<=count_1_sum[i] && count_1_sum[i]<=15 && count_1_sum[i+1]==1 )cmp_res[i/2]=4;
            // else if( 2<=count_1_sum[i] && count_1_sum[i]<=15 && 2<=count_1_sum[i+1] && count_1_sum[i+1]<=15 )cmp_res[i/2]=5;
            // else if( 2<=count_1_sum[i] && count_1_sum[i]<=15 && count_1_sum[i+1]==16 )cmp_res[i/2]=6;
            // else if( count_1_sum[i]==16 && count_1_sum[i+1]==1 )cmp_res[i/2]=7;
            // else if( count_1_sum[i]==16 && 2<=count_1_sum[i+1] && count_1_sum[i+1]<=15 )cmp_res[i/2]=8;
            // else if( count_1_sum[i]==16 && count_1_sum[i+1]==16 )cmp_res[i/2]=9;
        }


        for(int i=0;i<(4);i+=1){

            __m512i m512_encode_result = _mm512_loadu_epi64((&compress_result[8 * (i)])); // 读取8个64 bit值,当做ull处理
            __m512i m512_decode_result = _mm512_set1_epi64(0);

            //__m512i m512_decode_result = m512_decode_offset;

            //__m512i m512_decode_result2 = m512_decode_offset;

            //1.(m512_encode_result >> ceillog2_1_prefixsum[0])
            //2.result1 & mask[0]
            //3.result2 * 4
            //4.m512_stroageEncounterNum_4bit[0] >> result3
            //5.result4 & 15
            //6.result5 << (60-j*4)
            // m512_decode_result = 
            // (( (m512_stroageEncounterNum_4bit[0] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[0]) & mask[0]))) & 15) << (60-0*4)) |
            // (( (m512_stroageEncounterNum_4bit[1] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[1]) & mask[1]))) & 15) << (60-1*4)) |
            // (( (m512_stroageEncounterNum_4bit[2] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[2]) & mask[2]))) & 15) << (60-2*4)) |  
            // (( (m512_stroageEncounterNum_4bit[3] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[3]) & mask[3]))) & 15) << (60-3*4)) |  
            // (( (m512_stroageEncounterNum_4bit[4] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[4]) & mask[4]))) & 15) << (60-4*4)) |  
            // (( (m512_stroageEncounterNum_4bit[5] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[5]) & mask[5]))) & 15) << (60-5*4)) |  
            // (( (m512_stroageEncounterNum_4bit[6] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[6]) & mask[6]))) & 15) << (60-6*4)) |  
            // (( (m512_stroageEncounterNum_4bit[7] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[7]) & mask[7]))) & 15) << (60-7*4)) |
            // (( (m512_stroageEncounterNum_4bit[8] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[8]) & mask[8]))) & 15) << (60-8*4)) |  
            // (( (m512_stroageEncounterNum_4bit[9] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[9]) & mask[9]))) & 15) << (60-9*4)) |  
            // (( (m512_stroageEncounterNum_4bit[10] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[10]) & mask[10]))) & 15) << (60-10*4)) |  
            // (( (m512_stroageEncounterNum_4bit[11] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[11]) & mask[11]))) & 15) << (60-11*4)) |  
            // (( (m512_stroageEncounterNum_4bit[12] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[12]) & mask[12]))) & 15) << (60-12*4)) |  
            // (( (m512_stroageEncounterNum_4bit[13] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[13]) & mask[13]))) & 15) << (60-13*4)) |  
            // (( (m512_stroageEncounterNum_4bit[14] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[14]) & mask[14]))) & 15) << (60-14*4)) |  
            // (( (m512_stroageEncounterNum_4bit[15] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[15]) & mask[15]))) & 15) << (60-15*4))
            // ;


            // m512_decode_result = 
            // (( (m512_stroageEncounterNum_4bit[0] >> (((m512_encode_result << ceillog2_1_prefixsum[0]) & mask[0]))) & 15) << (60-0*4)) |
            // (( (m512_stroageEncounterNum_4bit[1] >> (((m512_encode_result << ceillog2_1_prefixsum[1]) & mask[1]))) & 15) << (60-1*4)) |
            // (( (m512_stroageEncounterNum_4bit[2] >> (((m512_encode_result << ceillog2_1_prefixsum[2]) & mask[2]))) & 15) << (60-2*4)) |  
            // (( (m512_stroageEncounterNum_4bit[3] >> (((m512_encode_result >> ceillog2_1_prefixsum[3]) & mask[3]))) & 15) << (60-3*4)) |  
            // (( (m512_stroageEncounterNum_4bit[4] >> (((m512_encode_result >> ceillog2_1_prefixsum[4]) & mask[4]))) & 15) << (60-4*4)) |  
            // (( (m512_stroageEncounterNum_4bit[5] >> (((m512_encode_result >> ceillog2_1_prefixsum[5]) & mask[5]))) & 15) << (60-5*4)) |  
            // (( (m512_stroageEncounterNum_4bit[6] >> (((m512_encode_result >> ceillog2_1_prefixsum[6]) & mask[6]))) & 15) << (60-6*4)) |  
            // (( (m512_stroageEncounterNum_4bit[7] >> (((m512_encode_result >> ceillog2_1_prefixsum[7]) & mask[7]))) & 15) << (60-7*4)) |
            // (( (m512_stroageEncounterNum_4bit[8] >> (((m512_encode_result >> ceillog2_1_prefixsum[8]) & mask[8]))) & 15) << (60-8*4)) |  
            // (( (m512_stroageEncounterNum_4bit[9] >> (((m512_encode_result >> ceillog2_1_prefixsum[9]) & mask[9]))) & 15) << (60-9*4)) |  
            // (( (m512_stroageEncounterNum_4bit[10] >> (((m512_encode_result >> ceillog2_1_prefixsum[10]) & mask[10]))) & 15) << (60-10*4)) |  
            // (( (m512_stroageEncounterNum_4bit[11] >> (((m512_encode_result >> ceillog2_1_prefixsum[11]) & mask[11]))) & 15) << (60-11*4)) |  
            // (( (m512_stroageEncounterNum_4bit[12] >> (((m512_encode_result >> ceillog2_1_prefixsum[12]) & mask[12]))) & 15) << (60-12*4)) |  
            // (( (m512_stroageEncounterNum_4bit[13] >> (((m512_encode_result >> ceillog2_1_prefixsum[13]) & mask[13]))) & 15) << (60-13*4)) |  
            // (( (m512_stroageEncounterNum_4bit[14] >> (((m512_encode_result >> ceillog2_1_prefixsum[14]) & mask[14]))) & 15) << (60-14*4)) |  
            // (( (m512_stroageEncounterNum_4bit[15] >> (((m512_encode_result >> ceillog2_1_prefixsum[15]) & mask[15]))) & 15) << (60-15*4))
            // ;


            // if(count_1_sum[0]==1){}
            // else if(count_1_sum[0]==16){m512_decode_result += (   ((m512_encode_result >> ceillog2_1_prefixsum[0]) & mask[0]) << (60-0*4));}
            // else{m512_decode_result += (( (m512_stroageEncounterNum_4bit[0] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[0]) & mask[0]))) & 15) << (60-0*4));}


           
            for(int j=0;j<16;++j){
                //运行时循环中不变量，分支预测正确率几乎100%，如何优化为无分支？
                if(count_1_sum[j]==1){ 
                    /* do nothing */
                }
                else if(count_1_sum[j]==16){
                    //似乎
                    //m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j] ) & 15 ) << (60 - j*4));

                    // if( (60-j*4 - ceillog2_1_prefixsum[j]) > 0){
                    //     m512_decode_result |= ( ((m512_encode_result & ( _mm512_set1_epi64(15ull) << ceillog2_1_prefixsum[j]) )) << (60 - j*4 - ceillog2_1_prefixsum[j]));
                    // }else{
                    //     m512_decode_result |= ( ((m512_encode_result & ( _mm512_set1_epi64(15ull) << ceillog2_1_prefixsum[j]) )) >> (-(60 - j*4 - ceillog2_1_prefixsum[j])));
                    // }
                    //m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j] ) & 15ull ) << (60 - j*4));
                }
                else{
                    //m512_decode_result |= (((m512_stroageEncounterNum_4bit[j] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j]) & mask[j]))) & 15) << (60 - j*4));
                }
                m512_decode_result += (( (m512_stroageEncounterNum_4bit[j] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j]) & mask[j]))) & 15) << (60-j*4));
            }



            // for(int j=0;j<8;++j){
            //     if(cmp_res[j]==1){
            //         //do nothing
            //         continue;
            //     }
            //     else if(cmp_res[j]==2){
            //         //j*2 do nothing
            //         m512_decode_result |= (((m512_stroageEncounterNum_4bit[j*2+1] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j*2+1]) & mask[j*2+1]))) & 15) << (60 - (j*2+1)*4));
            //         continue;
            //     }
            //     else if(cmp_res[j]==3){
            //         //j*2 do nothing
            //         m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j*2+1] ) & 15 ) << (60 - (j*2+1)*4));
            //         continue;
            //     }
            //     else if(cmp_res[j]==4){
            //         m512_decode_result |= (((m512_stroageEncounterNum_4bit[j*2] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j*2]) & mask[j*2]))) & 15) << (60 - (j*2)*4));
            //         //j*2+1 do nothing
            //         continue;
            //     }
            //     else if(cmp_res[j]==5){
            //         m512_decode_result |= (((m512_stroageEncounterNum_4bit[j*2] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j*2]) & mask[j*2]))) & 15) << (60 - (j*2)*4));
            //         m512_decode_result |= (((m512_stroageEncounterNum_4bit[j*2+1] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j*2+1]) & mask[j*2+1]))) & 15) << (60 - (j*2+1)*4));
            //         continue;
            //     }
            //     else if(cmp_res[j]==6){
            //         m512_decode_result |= (((m512_stroageEncounterNum_4bit[j*2] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j*2]) & mask[j*2]))) & 15) << (60 - (j*2)*4));
            //         m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j*2+1] ) & 15 ) << (60 - (j*2+1)*4));
            //         continue;
            //     }
            //     else if(cmp_res[j]==7){
            //         m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j*2] ) & 15 ) << (60 - (j*2)*4));
            //         //j*2+1 do nothing
            //         continue;
            //     }
            //     else if(cmp_res[j]==8){
            //         m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j*2] ) & 15 ) << (60 - (j*2)*4));
            //         m512_decode_result |= (((m512_stroageEncounterNum_4bit[j*2+1] >> (4 * ((m512_encode_result >> ceillog2_1_prefixsum[j*2+1]) & mask[j*2+1]))) & 15) << (60 - (j*2+1)*4));
            //         continue;
            //     }
            //     else [[likely]]
            //     {
            //         m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j*2] ) & 15 ) << (60 - (j*2)*4));
            //         m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j*2+1] ) & 15 ) << (60 - (j*2+1)*4));

            //         //m512_decode_result |= ( ((m512_encode_result >> ceillog2_1_prefixsum[j*2] ) & 255 ) << (60 - (j*2+1)*4));
            //         continue;
            //     }
                
            // }

            if(1){
                _mm512_storeu_epi64(res,m512_decode_result);
                for (int k = 0; k < 8; ++k)
                {
                    printf("input[%d]=%lf,res[%d]=%lf\n",k+8*i,input[k+8*i],k,res[k]);
                }
            }
            res_sum |= (m512_decode_result);
        }

        auto cycle6 = getcycle();
        auto time2 = std::chrono::system_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(time2 - time1).count();
        std::cout << "duration cycle: " << cycle5 - cycle1 << "  time ns : " << duration << "  time ms : " << duration / 1e6 << " one number : " << double(duration) / N << std::endl;
        std::cout << "memset cycle: " << cycle2 - cycle1 << "  percent:  " << double(cycle2 - cycle1) * 100 / (cycle6 - cycle1) << "%" << std::endl;
        std::cout << "loop input cycle: " << cycle3 - cycle2 << "  percent:  " << double(cycle3 - cycle2) * 100 / (cycle6 - cycle1) << "%" << std::endl;
        std::cout << "(cycle 3-4) cycle: " << cycle4 - cycle3 << "  percent:  " << double(cycle4 - cycle3) * 100 / (cycle6 - cycle1) << "%" << std::endl;
        std::cout << "encode cycle: " << cycle5 - cycle4 << " percent:  " << double(cycle5 - cycle4) * 100 / (cycle6 - cycle1) << " %  " << "bandwidth : " << double(N) * sizeof(double) / (1 << 30) / (std::chrono::duration_cast<std::chrono::nanoseconds>(time_encode_end - time_cycle3_end).count() / 1e9) << " GB/s " << std::endl;
        std::cout << "decode cycle: " << cycle6 - cycle5 << "  percent:  " << double(cycle6 - cycle5) * 100 / (cycle6 - cycle1) << "%" << std::endl;
        
        
        auto duration_cycle4_3 = std::chrono::duration_cast<std::chrono::nanoseconds>(time_cycle3_end - time_cycle3_start).count();
        std::cout << "time_cycle3_end - time_cycle3_start = " << duration_cycle4_3 << " ns" << std::endl;
        auto duration_cycle3_2 = std::chrono::duration_cast<std::chrono::nanoseconds>(time_cycle3_start - time_cycle2_start).count();
        std::cout << "time_cycle3_start - time_cycle2_start = " << duration_cycle3_2 << " ns  " << duration_cycle3_2 / 1e6 << " ms " << "meomery bandwidth : " << 1.0 * N * sizeof(double) / (1 << 30) / (duration_cycle3_2 / 1e9) << " GB/s" << std::endl;

        if (DECODEOK == 1)
            printf("all num encode decode success, sum=%d\n", DECODEOK);
        else
            printf("all num encode decode error, sum=%d\n", DECODEOK);

        // all_bit = ceillog2[sum1 - 1] +
        //           ceillog2[sum2 - 1] +
        //           ceillog2[sum3 - 1] +
        //           ceillog2[sum4 - 1] +
        //           ceillog2[sum5 - 1] +
        //           ceillog2[sum6 - 1] +
        //           ceillog2[sum7 - 1] +
        //           ceillog2[sum8 - 1];
        // printf("all_bit=%d\n", all_bit);
        // printf("sum1=%d\n", sum1);
        // printf("sum2=%d\n", sum2);
        // printf("sum3=%d\n", sum3);
        // printf("sum4=%d\n", sum4);
        // printf("sum5=%d\n", sum5);
        // printf("sum6=%d\n", sum6);
        // printf("sum7=%d\n", sum7);
        // printf("sum8=%d\n", sum8);
        // printf("min_bit=%d\n", int(
        //                            ceil(
        //                                log2((unsigned long long int)(sum1) *
        //                                     (unsigned long long int)(sum2) *
        //                                     (unsigned long long int)(sum3) *
        //                                     (unsigned long long int)(sum4) *
        //                                     (unsigned long long int)(sum5) *
        //                                     (unsigned long long int)(sum6) *
        //                                     (unsigned long long int)(sum7) *
        //                                     (unsigned long long int)(sum8)))));

        // printf("count5_0=%d\n", count5_0);
        // printf("count5_1=%d\n", count5_1);
        // printf("count5_2=%d\n", count5_2);
        // printf("count5_3=%d\n", count5_3);
        // printf("count5_4=%d\n", count5_4);
        // printf("count5_5=%d\n", count5_5);
        // printf("count5_6=%d\n", count5_6);
        // printf("count5_7=%d\n", count5_7);
        // printf("count5_8=%d\n", count5_8);
        // printf("count5_9=%d\n", count5_9);
        // printf("count5_10=%d\n", count5_10);
        // printf("count5_11=%d\n", count5_11);
        // printf("count5_rest4=%d\n", count5_rest4);

        printm512(0, res_sum);

        for (int i = 0; i < 8; ++i)
        {
            //printf("res[%d]=%lf\n",i,res[i]);
        }
        for (int i = 0; i < 16; ++i)
        {
            // printf("isExistRange0_15[%d]=%d\n",i,isExistRange0_15[i]);
        }
        for (int i = 0; i < 16; ++i)
        {
            // printf("count4bit_16[%d]=%d\n",i,count4bit_16[i]);
        }
        for (int i = 0; i < 16; ++i)
        {
            // printf("ans[%d]=%llu ans2[%d]=%llu\n",i,ans[i],i,ans2[i]);
        }

        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_1[i]);
        // }
        // printf("\n");
        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_2[i]);
        // }
        // printf("\n");
        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_3[i]);
        // }
        // printf("\n");
        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_4[i]);
        // }
        // printf("\n");
        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_5[i]);
        // }
        // printf("\n");
        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_6[i]);
        // }
        // printf("\n");
        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_7[i]);
        // }
        // printf("\n");
        // for(int i=0;i<32;++i){
        //      printf("%d ", isExistRange0_255_8[i]);
        // }
        // printf("\n");

        // encode

        // decode
    }

    return 0;
}